6

我正在尝试实现 Martin Odersky 的 CourseRa Scala 课程中显示的示例,以尝试使用适当的括号显示包含 Sums/Prods 的表达式。我想出了以下解决方案:

package expressions

trait Expr {
    def eval : Int = {
      this match {
        case Number(n) => n
        case Sum(e1,e2) => e1.eval + e2.eval
      }
    }
    //def show( exp : Expr) : String
}

case class Number(n:Int) extends Expr
case class Sum(e1: Expr, e2: Expr) extends Expr
case class Prod(e1 : Expr, e2 : Expr) extends Expr
case class Var(x:Char) extends Expr

object testExpr {
  def show(exp : Expr) : String = {
    exp match {
      case Number(x) => x.toString()
      case Sum(e1, e2) => show(e1) + "+" + show(e2)
      case Prod(e1,e2) => 
        val st1 = e1 match {
          case Sum(a,b) => "(" + show(Sum(a,b)) + ")"
          case _ => show(e1)
        }
        val st2 = e2 match {
          case Sum(a,b) => "(" + show(Sum(a,b)) + ")"
          case _ => show(e2)
        }
        st1 + "*" + st2
      case Var(x) => x.toString
    }
  }
}

object test extends App{

  println(testExpr.show(Sum(Number(1),Number(2))))
  println(Sum(Number(1),Number(3)).eval)
  println(testExpr.show(Sum(Number(2),Prod(Number(10),Var('x')))))

  println(testExpr.show(Sum(Prod(Number(2),Var('x')),Var('y'))))
  println(testExpr.show(Prod(Sum(Number(2),Var('x')),Var('y'))))
  println(testExpr.show(Prod(Sum(Number(2),Var('x')),Sum(Number(3),Var('y')))))
}

我决定放置括号的方式绝对不是最好的解决方案。任何人都可以提出更好的解决方案来实现同样的目标。

谢谢和问候, 帕罗米塔

4

3 回答 3

6

有点类似于 ParoTech 和 Val 的,只是稍微干燥:

def show(e: Expr): String = {

  def paren(e:Expr) = {
    e match {
      case Sum(_, _) => "(" + show(e) + ")"
      case _ => show(e)
    }
  }

  e match {
    case Number(n) => n.toString
    case Var(s) => s
    case Sum(e1, e2) => show(e1) + " + " + show(e2)
    case Prod(e1, e2) => paren(e1) + " * " + paren(e2)
  }

}
于 2015-02-02T09:25:37.833 回答
5

你实际上非常接近。我想出的代码如下:

case Variable(name) => name

case Product(e1, e2) => "%s * %s".format(
  e1 match {
    case Sum(_, _) => "(%s)".format(show(e1))
    case _ => show(e1)
  },
  e2 match {
    case Sum(_, _) => "(%s)".format(show(e2))
    case _ => show(e2)
  }
)

这将使用元组匹配进一步重写为

case Product(e1, e2) =>
  val format = (e1, e2) match {
    case (Sum(_, _), _) => "(%s) * %s"
    case (_, Sum(_, _)) => "%s * (%s)"
    case (_, _) => "%s * %s"
  }
  format.format(show(e1), show(e2))
于 2013-11-27T03:19:53.987 回答
2

我想应该的解决方案是前缀

   case Prod(l, r) => show(l) + "*" + show(r)

   case Prod(Sum(sl, sr), r) => "(" + show(sl) + " + " + show(sr) + ")" + "*" + show(r)

如此处所示https://github.com/glebd/scala-course/blob/master/workspace/hello-project/src/week4/exprs.sc

结果代码是

  def show(e: Expr): String = e match {
      case Number(n) => n.toString
      case Var(v) => v
      case Prod(Sum(e1, e2), Sum(e3, e4)) => "(" + show(e1) + "+" + show(e2) + ")*(" + show(e3) + "+" + show(e4) + ")"
      case Prod(Sum(e1, e2), e3) => "(" + show(e1) + "+" + show(e2) + ")*" + show(e3)
      case Prod(e1, Sum(e2, e3)) => show(e1) + "*(" + show(e2) + "+" + show(e3) + ")"
      case Sum(e1, e2) => show(e1) + "+" + show(e2)
      case Prod(e1, e2) => show(e1) + "*" + show(e2)
  } 

我不知道 Krupennik 的解决方案应该做什么。Oderski 没有展示这样的结构。但这个解决方案揭示了 Krupennik 正在做的事情。

于 2014-06-22T16:57:22.940 回答