класс дела и черты - PullRequest
       41

класс дела и черты

6 голосов
/ 03 сентября 2010

Я хочу создать специальный калькулятор.Я думаю, что case class - хорошая идея для операций:

sealed class Expr
case class add(op1:Int, op2:Int) extends Expr
case class sub(op1:Int, op2:Int) extends Expr
case class mul(op1:Int, op2:Int) extends Expr
case class div(op1:Int, op2:Int) extends Expr
case class sqrt(op:Int) extends Expr
case class neg(op:Int) extends Expr
/* ... */

Теперь я могу использовать регистр совпадений для анализа ввода.Может быть, я должен также использовать traits (то есть: trait Distributivity, trait Commutativity и т. Д.), Это возможно?Это хорошая идея?

1 Ответ

13 голосов
/ 03 сентября 2010

Прежде чем вы начнете добавлять черты не столь ясной дополнительной ценности, вы должны правильно понять основы. То, как вы делаете это сейчас, делает эти классы не очень полезными, по крайней мере, при построении классического AST (или "дерева разбора"). Представь себе 4 * (3 + 5). Прежде чем вы сможете использовать операцию умножения, вы должны оценить сложение в первую очередь. Это усложняет ситуацию. Как правило, вы хотите иметь возможность написать свою формулу «сразу», например, Mul (4, Add (3, 5)). Однако это не сработает, так как вы не можете получить Ints или Doubles в свою собственную иерархию классов. Обычное решение - это класс-оболочка для Numbers, скажем, «Num». Тогда мы имеем: Mul (Num (4), Add (Num (3), Num (5)). Это может показаться сложным, но теперь у вас есть «все сразу», и вы можете делать такие вещи, как введение констант и переменных, упрощение (например, Mul (Num (1), x) -> x), деривация ...

Чтобы получить это, вам нужно что-то вроде

sealed trait Expr {
  def eval:Int      
}
case class Num(n:Int) extends Expr {
  def eval = n
}
case class Neg(e: Expr) extends Expr {
  def eval = - e.eval() 
}
case class Add(e1: Expr, e2: Expr) extends Expr {
  def eval = e1.eval + e2.eval  
}
...

Теперь вы можете написать парсер, который превращает "4 * (3 + 5)" в Mul (Num (4), Add (Num (3), Num (5))) и получить результат, вызвав для этого eval выражение.

Scala уже содержит библиотеку синтаксического анализа, называемую комбинаторы синтаксического анализа. Пример, близкий к приведенному выше, см. В http://jim -mcbeath.blogspot.com / 2008/09 / scala-parser-combinators.html

...