transform a given example from a visitor pattern to using pattern matching.
The following code example shows evaluation and printing of simple arithmetic expressions using a visitor pattern. (The
Code: Alles auswählen
task follows on the next page.)
////// Class hierarchy
trait Expr {
def accept[Result](v: Visitor[Result]): Result
}
case class Constant(val value: Int) extends Expr {
def accept[Result](v: Visitor[Result]) = v.visit(this)
}
case class Var(val name: String) extends Expr {
def accept[Result](v: Visitor[Result]) = v.visit(this)
}
case class Add(val left: Expr , val right: Expr) extends Expr {
def accept[Result](v: Visitor[Result]) = v.visit(this)
}
case class Mul(val left: Expr , val right: Expr) extends Expr {
def accept[Result](v: Visitor[Result]) = v.visit(this)
}
////// Visitors
trait Visitor[Result] {
def visit(e: Constant): Result
def visit(e: Add): Result
def visit(e: Mul): Result
def visit(e: Var): Result
}
class EvalVisitor(env: Map[String , Int]) extends Visitor[Int] {
def visit(e: Constant) = e.value
def visit(e: Add) = e.left.accept(this) + e.right.accept(this)
def visit(e: Mul) = e.left.accept(this) * e.right.accept(this)
def visit(e: Var) = env(e.name)
}
class FormatVisitor extends Visitor[String] {
def visit(e: Constant) = e.value.toString
def visit(e: Add) = s"(${e.left.accept(this)} + ${e.right.accept(this)})"
def visit(e: Mul) = s"(${e.left.accept(this)} * ${e.right.accept(this)})"
def visit(e: Var) = e.name
}
object VisitorExpr extends App {
val testExpr = Add(Mul(Constant(2),Var("x")), Constant(5))
println(testExpr.accept(new FormatVisitor()))
println(testExpr.accept(new EvalVisitor(Map("x" -> 7))))
}
Code: Alles auswählen
class VisitorToStrategy
abstract trait Expr
final case class Constant(val n: Int) extends Expr
final case class Add(val left: Expr, val right: Expr) extends Expr
final case class Mul(val left: Expr, val right: Expr) extends Expr
final case class Var(val v: String) extends Expr
class Impl {
def eval(exp: Expr, ref: Map[String, Int]) : Int = exp match {
case Constant(n) => n
case Add(left, right) => eval(left, ref) + eval(right, ref)
case Mul(left, right) => eval(left, ref) * eval(right, ref)
case Var(v) => ref(v)
}
def format(exp: Expr, ref: Map[String, Int]) : Unit = exp match {
case Constant(n) => print(n)
case Add(left, right) => print(s"(${eval(left, ref)} + ${eval(right, ref)})")
case Mul(left, right) => print(s"(${eval(left, ref)} * ${eval(right, ref)})")
case Var(v) => print(v)
}
}
object VisitorExpr extends App {
val x = new Constant(5)
val y = new Constant(5)
val map = Map("x" -> 5)
val impl = new Impl
val testExpr = Add(Mul(Constant(2),Var("x")), Constant(5))
impl.format(testExpr, null)
}