символьное дифференцирование в Scala

Я хочу создать функцию символьного дифференцирования в Scala, используя сопоставление с образцом, как это сделано в SICP. Я хотел бы иметь возможность написать что-то вроде этого:

differentiate(exp) = exp match
{
  case + => 
  case * =>
}

Возможно ли это в Scala на «родных» выражениях?


person Frawr    schedule 02.03.2012    source источник
comment
Вы имеете в виду def differentiate (exp: T) = ...? Какой тип опыта? Строка? Функция? Оба не подходят только для «+» или «*».   -  person user unknown    schedule 03.03.2012
comment
Возможно, это послужило источником вдохновения для вашего вопроса, но если вы еще этого не видели, посмотрите расширенный пример в главе «Сопоставление с образцом» книги «Программирование на Scala» (artima.com/pins1ed/case-classes-and-pattern-matching.html)   -  person Luigi Plinge    schedule 04.03.2012
comment
@LuigiPlinge Мне действительно предложили это, но я хотел посмотреть, нужно ли мне делать это дерево самому.   -  person Frawr    schedule 08.03.2012


Ответы (3)


Все примеры, которые я видел раньше, включают дерево выражений. Вы можете легко построить его на Scala с классами case. Например, грубый набросок, включающий сопоставление с образцом и объектно-ориентированный стиль:

trait Exp {
  def differentiate: Exp
}
case class Const( value: Double ) extends Exp {
  def differentiate = Const(0)
}
case class Var( label: String, power: Double ) extends Exp {
  def differentiate = this match {
    case Var(l,0.0) => Const(0)
    case Var(l,p) => Mul( Const(p), Var(l,p-1) )
  }
}
case class Add( left: Exp, right: Exp ) extends Exp {
  def differentiate = Add( left.differentiate, right.differentiate )
}
case class Mult( left: Exp, right: Exp ) extends Exp {
  def differentiate = ( left, right ) match {
    case ( Const(c), exp ) => Mul( Const(c), exp.differentiate )
    case ( exp, Const(c) ) => Mul( Const(c), exp.differentiate )
    case (e1, e2) => Add( Mul( e1.differentiate, e2), Mul( e1, e2.differentiate ) )
  }
}
person paradigmatic    schedule 03.03.2012

Вы пробовали? :)

sealed trait Exp
case object + extends Exp
case object * extends Exp

def differentiate(exp: Exp) = exp match {
  case + => println("plus")
  case * => println("times")
}

scala> differentiate(*)
times

Но

scala> differentiate(+)
<console>:1: error: illegal start of simple expression
       differentiate(+)
                  ^

Хм, я думаю, это не работает для всех символов.

person Luigi Plinge    schedule 02.03.2012
comment
Хотя вы можете вызвать его с помощью differentiate($plus). - person Luigi Plinge; 03.03.2012
comment
Является ли проблема с «+» ошибкой? - person soc; 03.03.2012
comment
@soc Я не знаю, в частности, о +, но, конечно, вы ожидаете, что некоторые символы (зарезервированные символы, такие как {, ; и т. д.) не будут работать. - person Luigi Plinge; 04.03.2012

На "родных" выражениях - нет. Не совсем. Вы можете использовать символы:

def foo(x: Symbol) = x match {
  case '+ => "Plus"
  case '* => "Times"
}

Если вы заметили, символы также используются SICP для синтаксического анализа. См. SICP 2.3.1

(deriv '(* x y) 'x)
y

У него может быть более красивый синтаксис для сопоставления символов, но, в конце концов, это все, что он делает.

person Dan Burton    schedule 02.03.2012