scala - 案例分类和特征

标签 scala traits case-class

我想创建一个特殊的计算器。我认为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 Distributivitytrait Commutativity等),这可行吗?这是一个好主意吗?

最佳答案

在开始添加不太明显的附加值特征之前,您应该了解基础知识。现在,您的操作方式使这些类不是很有用,至少在构建经典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

关于scala - 案例分类和特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3634222/

相关文章:

rust - 需要 Rust 特征边界中的交换操作

parsing - 轻松将 Key=Value 对的字符串解析为 Scala 案例类

scala - 通过特征覆盖方法时如何调用 super 方法

json - 如何从 scala 案例类中装饰不可变对象(immutable对象)图

scala - 抽象案例类

java - 计算 SHA-2 或 SHA-3 哈希值

scala - Martin Odersky 的 ScalaDay 2011 示例 : Yielding a Map?

postgresql - 使用 Mockito 模拟具有功能参数的 Scala 方法

scala - 如何避免 map 连接的奇怪顺序? (A++B++C ---> BAC)

enums - 解构枚举时是否可以向上转换为特征?