6

専用の電卓を作りたい。私はそれ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 Distributivityなどtrait Commutativity)、それは可能ですか? それは良い考えですか?

4

1 に答える 1

13

あまり明確でない付加価値の特性を追加する前に、基本を正しく理解する必要があります。現在のやり方では、これらのクラスはあまり役に立ちません。少なくとも、従来の AST (または「解析ツリー」) を構築するときはそうではありません。4 * (3+5) を想像してください。乗算演算を使用する前に、評価する必要があります最初に追加。それは物事を複雑にします。通常は、Mul(4,Add(3, 5)) のように、数式を「一度に」記述できる機能が必要です。ただし、Ints または Doubles を独自のクラス階層に入れることができないため、そのようには機能しません。通常の解決策は、「Num」などの Numbers のラッパー クラスです。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を参照してください。

于 2010-09-03T11:59:23.443 に答える