病例类别和特征

发布于 2024-09-17 17:17:42 字数 520 浏览 10 评论 0原文

我想创建一个特殊的计算器。我认为 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
/* ... */

现在我可以使用 match-case 来解析输入。 也许,我还应该使用traits(即:trait Distributivitytrait Commutativity等),这可能吗?这是个好主意吗?

I want create a special calculator. I think that case class is a good idea for operations:

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
/* ... */

Now I can use match-case for parsing input.
Maybe, I should also use traits (ie: trait Distributivity, trait Commutativity and so on), Is that posible? Is that a good idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半葬歌 2024-09-24 17:17:42

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

Before you start adding traits of not-so-clear additional value, you should get the basics right. The way you do it now makes these classes not very useful, at least not when building a classical AST (or "parse tree"). Imagine 4 * (3+5). Before you can use the multiplication operation, you have to evaluate the addition first. That makes things complicated. What you usually want to have is the ability to write your formula "at once", e.g. Mul(4,Add(3, 5)). However that won't work that way, as you can't get Ints or Doubles into your own class hierarchy. The usual solution is a wrapper class for Numbers, say "Num". Then we have: Mul(Num(4),Add(Num(3), Num(5)). This might look complicated, but now you have "all at once" and you can do things like introducing constants and variables, simplification (e.g. Mul(Num(1),x) --> x), derivation...

To get this, you need something along the lines

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  
}
...

Now you can write a parser that turns "4*(3+5)" into Mul(Num(4),Add(Num(3), Num(5)), and get the result by calling eval on that expression.

Scala contains already a parse library called parser combinators. For an example close to the code above see http://jim-mcbeath.blogspot.com/2008/09/scala-parser-combinators.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文