【问题标题】:case class and traits案例类别和特征
【发布时间】:2011-04-07 17:55:40
【问题描述】:

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

【问题讨论】:

  • 尝试不使用。您是否发现自己缺少这些特质赋予您的能力?

标签: scala traits case-class


【解决方案1】:

在您开始添加附加价值不那么明确的特征之前,您应该掌握基本知识。您现在这样做的方式使这些类不是很有用,至少在构建经典 AST(或“解析树”)时不是。想象一下 4 * (3+5)。在您可以使用乘法运算之前,您必须先评估加法。这使事情变得复杂。您通常想要的是“立即”编写公式的能力,例如穆尔(4,加(3, 5))。但是那样做是行不通的,因为您不能将 Ints 或 Doubles 放入您自己的类层次结构中。通常的解决方案是数字的包装类,比如“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

【讨论】:

  • @isola009 Landei 贡献了他的时间和精力来写这个答案。如果他的回答不合适,请花时间澄清您的问题。
  • 我的英语很差,我不知道我的问题。对不起。
  • 也许可以给出一些代码示例(或伪代码)来展示你想对这些类做什么,并解释(尽你所能)你对分布性、交换性等的看法。特质可能会帮助你....
  • 我真正想做的比较复杂。这只是一个例子。我所做的是一个好的设计。通用的答案就足够了。
猜你喜欢
  • 2018-06-02
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
  • 1970-01-01
  • 2016-11-26
  • 2012-10-22
  • 2011-11-27
  • 1970-01-01
相关资源
最近更新 更多