【发布时间】:2021-01-28 14:32:34
【问题描述】:
我正在采用一些预定义的语义规则,并将它们作为使用 Scala 的生菜语言的解释器来实现。在 Multi-Let 中,我尝试使用两个列表更新环境变量。我对 Scala 有点陌生,所以我不太确定如何在不将环境变量转换为 List 的情况下执行此操作。有没有办法在我的 zip 函数中操作返回类型?我收到以下错误消息。我的目标是获取单个更新地图,而不是更新地图列表。
cmd2.sc:44: type mismatch;
found : List[scala.collection.immutable.Map[String,Helper.this.Value]]
required: Helper.this.Environment
(which expands to) scala.collection.immutable.Map[String,Helper.this.Value]
evalExpr(e2,newEnv)
^Compilation Failed
sealed trait Expr
case class Const(d: Double) extends Expr
case class Ident(s: String) extends Expr
case class Plus(e1: Expr, e2: Expr) extends Expr
case class Mult(e1: Expr, e2: Expr) extends Expr
case class Let(id: String, e1: Expr, e2: Expr) extends Expr
case class MultiLet(id: List[String], eList: List[Expr], e2: Expr) extends Expr
sealed trait Value
case class NumValue(f: Double) extends Value
case object Error extends Value /* -- Do not return Error -- simply throw an new IllegalArgumentException whenever you encounter an erroneous case --*/
type Environment = Map[String, Value]
def evalExpr(e: Expr, env: Environment): Value = {
e match {
case Let(x, e1, e2) => {
val v1 = evalExpr(e1, env)
val newEnv = env.updated(x,v1);
evalExpr(e2,newEnv)
}
case MultiLet(xList, eList, e2) => {
val vList = eList.map(evalExpr(_, env))
val newEnv = (xList, vList).zipped.map{ (x, v) => env.updated(x,v)}
println(newEnv)
evalExpr(e2,newEnv)
}
}
}
【问题讨论】:
-
您似乎想要
foldLeft(env) { case (e, (x, y)) => e.updated(x, y) },或者只是将所有值都放在++。但我认为它不能正常工作:eList.map(evalExpr(_, env))将评估旧环境中的所有右手边,但您需要更新的环境才能使所有相互递归的定义正常工作,不是吗? -
@AndreyTyukin 是正确的。我可能把那部分弄错了。这是一个老问题的建议。我打算先完成
case MultiLet,然后根据我预先构建的测试用例编译整个事情
标签: scala pattern-matching environment interpreter semantics