我对scala有点新意,我在这里有一个程序可以完成我想要的一切,除了一件我似乎无法弄清楚的事情。我有表达式,我基于一些简单的数学规则简化表达式。然后我提示用户绑定变量并用用户键入的整数替换变量,然后计算表达式。这一切都像我想要的那样。但是,当我不将特定变量替换为整数时,我仍然想要简化/评估表达式。我只是简单地评估表达式而不要求用户输入x的值,我删除了在我的环境中替换x的语句。问题是当eval方法在我的表达式中遇到x时调用env时,我得到一个scala.Match错误。为了更清楚我想要做的是用我的例子中的表达式。表达式:(x +(x *(y - (z / 2))))只用2代替变量y和z,我希望看到的结果是(x + x)。我将不胜感激任何建议/帮助!我的程序在这一点看起来像这样:
var n1 = 0
var n2 = 0
var n3 = 0
type Environment = String => Int
lazy val exp: Tree = Sum(Var("x"), Times(Var("x"), Minus(Var("y"), Divide(Var("z"), Const(2)))))
lazy val env: Environment = {
case "x" => n1 //take this line out to not bind x
case "y" => n2
case "z" => n3
}
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " + " + r + ")"
}
case class Minus(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " - " + r + ")"
}
case class Times(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " * " + r + ")"
}
case class Divide(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " / " + r + ")"
}
case class Var(n: String) extends Tree {
override def toString = n
}
case class Const(v: Int) extends Tree {
override def toString = v.toString
}
def simplify(t: Tree): Tree = t match {
case Times(Const(1), r) => simplify(r)
case Times(l, Const(1)) => simplify(l)
case Times(Const(0), r) => Const(0)
case Times(l, Const(0)) => Const(0)
case Sum(Const(0), r) => simplify(r)
case Sum(l, Const(0)) => simplify(l)
case Minus(l, Const(0)) => simplify(l)
case Minus(l, r) if l == r => Const(0)
case Divide(Const(0), r) => Const(0)
case Divide(l, Const(1)) => simplify(l)
case Divide(l, r) if l == r => Const(1)
case Times(l, r) => Times(simplify(l), simplify(r))
case Sum(l, r) => Sum(simplify(l), simplify(r))
case Minus(l, r) => Minus(simplify(l), simplify(r))
case Divide(l, r) => Divide(simplify(l), simplify(r))
case _ => t
}
def eval(t: Tree): Int = t match {
case Sum(l, r) => eval(l) + eval(r)
case Minus(l, r) => eval(l) - eval(r)
case Times(l, r) => eval(l) * eval(r)
case Divide(l, r) => eval(l) / eval(r)
case Var(n) => env(n)
case Const(v) => v
}
println("Expression: " + exp)
println("Simplified: " + simplify(exp))
println("Enter the binding for x.") //take this line out to not bind x
n1 = readInt() //take this line out to not bind x
println("Enter the binding for y.")
n2 = readInt()
println("Enter the binding for z.")
n3 = readInt()
println("Evaluation: " + eval(exp))
答案 0 :(得分:1)
我稍微改变了你的代码,让它按你的意愿工作:
abstract class Tree
case class Sum(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " + " + r + ")"
}
case class Minus(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " - " + r + ")"
}
case class Times(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " * " + r + ")"
}
case class Divide(l: Tree, r: Tree) extends Tree {
override def toString = "(" + l + " / " + r + ")"
}
case class Var(n: String) extends Tree {
override def toString = n
}
case class Const(v: Int) extends Tree {
override def toString = v.toString
}
object ExprEval {
lazy val exp: Tree = Sum(Var("x"), Times(Var("x"), Minus(Var("y"), Divide(Var("z"), Const(2)))))
var env = Map[String, Int]()
def simplify(t: Tree, recursive : Boolean = true): Tree = {
t match {
case Sum(Const(0), r) => simplify(r)
case Sum(l, Const(0)) => simplify(l)
case Sum(Const(l), Const(r)) => Const(l + r)
case Sum(Var(l), Var(r)) if l == r => Times(Const(2), Var(l))
case Sum(l, r) if recursive => simplify(Sum(simplify(l), simplify(r)), recursive = false)
case Minus(l, Const(0)) => simplify(l)
case Minus(l, r) if l == r => Const(0)
case Minus(Const(l), Const(r)) => Const(l - r)
case Minus(l, r) if recursive => simplify(Minus(simplify(l), simplify(r)), recursive = false)
case Times(Const(1), r) => simplify(r)
case Times(l, Const(1)) => simplify(l)
case Times(Const(0), r) => Const(0)
case Times(l, Const(0)) => Const(0)
case Times(Const(l), Const(r)) => Const(l * r)
case Times(l, r) if recursive => simplify(Times(simplify(l), simplify(r)), recursive = false)
case Divide(Const(0), r) => Const(0)
case Divide(l, Const(1)) => simplify(l)
case Divide(l, r) if l == r => Const(1)
case Divide(Const(l), Const(r)) => Const(l / r)
case Divide(l, r) if recursive => simplify(Divide(simplify(l), simplify(r)), recursive = false)
case Var(n) => env.get(n).map(Const).getOrElse(Var(n))
case _ => t
}
}
def eval(t: Tree): Int = t match {
case Sum(l, r) => eval(l) + eval(r)
case Minus(l, r) => eval(l) - eval(r)
case Times(l, r) => eval(l) * eval(r)
case Divide(l, r) => eval(l) / eval(r)
case Var(n) => env(n)
case Const(v) => v
}
def main(args: Array[String]) {
env = Map()
println(s"env: $env, exp : $exp, simplified : ${simplify(exp)}")
env = Map("y" -> 2, "z" -> 2)
println(s"env: $env, exp : $exp, simplified : ${simplify(exp)}")
env = Map("z" -> 4)
println(s"env: $env, exp : $exp, simplified : ${simplify(exp)}")
env = Map("x" -> 3, "y" -> 2, "z" -> 2)
println(s"env: $env, exp : $exp, simplified : ${simplify(exp)}")
}
}
如果没有绑定变量,则返回简化的原始表达式树。如果绑定了所有变量,它将产生与eval()相同的结果。
输出:
env: Map(), exp : (x + (x * (y - (z / 2)))), simplified : (x + (x * (y - (z / 2))))
env: Map(y -> 2, z -> 2), exp : (x + (x * (y - (z / 2)))), simplified : (2 * x)
env: Map(z -> 4), exp : (x + (x * (y - (z / 2)))), simplified : (x + (x * (y - 2)))
env: Map(x -> 3, y -> 2, z -> 2), exp : (x + (x * (y - (z / 2)))), simplified : 6
答案 1 :(得分:1)
这是一个相对干净的解决方案。我只包括了我修改的部分。
type Environment = String => Option[Int]
lazy val env: Environment = {
case "y" => Some(n2)
case "z" => Some(n3)
case _ => None
}
def simplify(t: Tree): Tree = {
val reducedTree = t match {
case Times(l, r) => Times(simplify(l), simplify(r))
case Sum(l, r) => Sum(simplify(l), simplify(r))
case Minus(l, r) => Minus(simplify(l), simplify(r))
case Divide(l, r) => Divide(simplify(l), simplify(r))
case Var(n) => env(n).map(Const).getOrElse(t)
case _ => t
}
reducedTree match {
case Times(Const(1), r) => r
case Times(l, Const(1)) => l
case Times(Const(0), r) => Const(0)
case Times(l, Const(0)) => Const(0)
case Times(Const(l), Const(r)) => Const(l * r)
case Sum(Const(0), r) => r
case Sum(l, Const(0)) => l
case Sum(Const(l), Const(r)) => Const(l + r)
case Minus(l, Const(0)) => l
case Minus(l, r) if l == r => Const(0)
case Minus(Const(l), Const(r)) => Const(l - r)
case Divide(Const(0), r) => Const(0)
case Divide(l, Const(1)) => l
case Divide(l, r) if l == r => Const(1)
case Divide(Const(l), Const(r)) => Const(l / r)
case _ => reducedTree
}
}