【问题标题】:Evaluation tree评估树
【发布时间】:2017-01-21 02:49:30
【问题描述】:

我希望为初学者构建一个评估树,用于算术表达式。

我定义了以下案例类:

abstract class Expr
case class Num(n: Integer) extends Expr
case class Plus(e1: Expr, e2: Expr) extends Expr

我的解析器在看到表达式 1 + 1 + 1 时会生成以下树:

Plus(Plus(Num(1), Num(1)), Num(1))

然后我定义了以下数据类型:

case class Tree[Expr](e: Expr, children: List[Tree[Expr]])

这是一个画得很糟糕的评估树:

  Num(1)         Num(1)
----------------------------    
     Plus(Num(1), Num(1))         Num(1)
 ---------------------------------------
     Plus(Plus(Num(1),Num(1)), Num(1))

我想建立一个树形数据结构来表示它。因此,评估的结果输出将是:

Tree(
  Plus(Plus(Num(1), Num(1)), Num(1)),
  List(Tree(Plus(Num(1),Num(1),
       List(Tree(Num(1), List()),
            Tree(Num(1), List()))),
  Tree(Num(1), List())))

我想要一个方法 eval:

def eval(e: Expr, t: Tree[Expr]): Tree[Expr] = (e, t) match {
  // Do the matching on Num
  case Num(n) ........ =>
  case Plus(e1, e2)  ...... => 
}

这是表示这个评估树的正确方法吗?如果是,我该如何创建这样一个嵌套的树数据结构。

编辑:这是一个仅用于添加的方法 eval

def eval(e: Expr): Tree[Expr] = e match {
    case Num(n) => Tree(Num(n), Nil)
    case Plus(e1, e2) => Tree(Plus(e1, e2), List(eval(e1), eval(e2)))
}

【问题讨论】:

  • 我认为你不需要树类。您已经通过嵌套 Pluses 创建了一棵树
  • 不是任务,是我的项目。我的解析器生成了一个嵌套树,它是初始表达式。我在帖子中画了评估树。我更新了上面的帖子,在那里我想出了只有添加的语言的解决方案。
  • 我没有说任何关于作业的事情。我仍然看不到 Tree 类的优势,Plus 类本身就已经是一棵树了。
  • 我在看了更多之后才明白你的意思。谢谢你的评论。

标签: scala tree


【解决方案1】:

你可能会这样:

def toTree(e: Expr): Tree[Expr] = e match {
  case Plus(e1, e2) => Tree(e, List(eval(e1), eval(e2)))
  case _ => Tree(e, List())
}

但是,您最好按照@puhlen 的建议省略Tree。以下方法应该足够了:

def children(e: Expr): List[Expr] = e match {
  case Plus(e1, e2) => List(e1, e2)
  case _ => List()
}

在任何你想使用Tree.children的地方使用它

【讨论】:

  • 那么另一个问题。此评估树将用于为其生成 HTML。每个案例类都有漂亮的打印方法,它将 lambda 显示为 lambda char 等。但是,这是用于遍历并将其呈现为 HTML 的正确数据结构吗?
  • 我还没有看到这个结构有任何问题。 pretty 可以通过类似于children 的模式匹配轻松实现。
  • 我写了类似的东西:zeroturnaround.com/rebellabs/parsing-lambda-calculus-in-scala 并继续将它应用到我更复杂的语言中。到目前为止看起来还不错,但我也想知道是否拥有由案例类实现的 Expr 特征,然后每个重写漂亮的方法。此外,当我有类型时,我发现很难合并 PrettyPrinter。类型不是 Expr,它们是 Type 类型,所以我可能需要让 PrettyPrinter 成为一种多态的打印机。有什么想法吗?
  • (1) 在函数式编程中你通常不需要override 方法。上面的children 没有覆盖任何东西——它是一个独立的方法,在一个地方包含所有逻辑。 (2) 当您处理自己的语言时,类型可以被视为类似于数据。 Scala 有一些类型 API 来匹配类型。你可以看看几个问题:stackoverflow.com/search?q=match+TypeRef,stackoverflow.com/questions/12842729/…
猜你喜欢
  • 2021-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 2017-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多