5

我正在为 scala 寻找一个简单的 CAS 系统。

它应具有以下特点:

  • 提供对抽象语法树的访问权限(最好通过案例类以便于匹配)
  • 解析String为 AST
  • 简化表达式

如果不存在并且我必须自己写一些基本的东西,那么最好的表示是什么?

我在想这样的事情:

abstract trait Term
{
  def simplify:Term
  def evaluate(assignment:Var => Double):Double
  def derivative:Term
}

case class Const(c:Int) extends Term
case class Var(x:String) extends Term

case class Negate(x:Term) extends Term
case class Subtract(x:Term, y:Term) extends Term
case class Divide(x:Term, y:Term) extends Term


object Add { def apply(x:Term*):Add = Add(x.toList) }
case class Add(xs : List[Term]) extends Term

object Multiply { def apply(x:Term*):Multiply = Multiply(x.toList) }
case class Multiply(xs:List[Term]) extends Term

case class Power(x:Term, y:Term) extends Term
case class Exp(x:Term) extends Term

我会实现这里描述的简化算法,这看起来很乏味。(但在简化代数表达式时,也许乏味是不可避免的?)

对这个特定实现的一些批评是:

  • 我将在simplify所有地方递归调用案例类的参数(似乎它可以以某种方式集中)
  • 处理 varargs /List参数似乎会变得Add混乱Mutliply
4

1 回答 1

4

我不知道 Scala 的现有 CAS。

在进行语言处理时,我通常发现在密封的层次结构上使用模式匹配比使用 OO 风格的多态性更令人愉快。由于添加新的术语类型很少见(这意味着语言的变化)并且添加新的操作很常见,因此表达式问题的这一面似乎更适合。

sealed trait Term
case class Const(c : Double) extends Term
case class Var(x : String) extends Term
case class Negate(x : Term) extends Term
case class Multiply(xs : List[Term]) extends Term
// etc

object CAS {

  // I assume that the assignment map may be incomplete, thus
  // evaluation is really a partial substitution and then simplification
  def evaluate(t : Term, assignment : Var => Option[Double]) : Term = t match {
    case _ : Const => t
    case v : Var => assignment(v) map Const getOrElse v
    case Negate(x) => evaluate(Multiply(Const(-1) :: evaluate(x, assignment) :: Nil), assignment)
    case Multiply(ts) => {
      val evalTs = ts map { t => evaluate(t, assignment) }
      val flattened = evalTs flatMap {
         case Multiply(subs) => subs
         case t => List(t)
      }
      val constTotal = Const((flattened collect { case Const(c) => c }).product)
      val otherTerms = flattened filter { case t : Const => false; case _ => true }
      (constTotal, otherTerms) match {
         case (Const(0), _) => Const(0)
         case (Const(1), Nil) => Const(1)
         case (Const(1), _) => Multiply(otherTerms)
         case _ => Multiply(constTotal +: otherTerms)
      }
    }
    // etc

  }

  private val emptyAssignment : (Var => Option[Double]) = { x : Var => None }

  // simplfication is just evaluation with an empty assignment
  def simplify(t : Term) : Term = evaluate(t, emptyAssignment)
}

我一直想学习但没有学习的一项技术是属性语法。他们应该从这种 AST 处理中消除大部分的乏味。有关Scala 实现,请参阅 kiama http://code.google.com/p/kiama/

顺便说一句,虽然我在这里为您的域使用双打,但您最好使用“大理性”——一对 BigInteger。它们很慢但非常精确。

于 2011-05-18T15:38:18.893 回答