## Exam Question: Visitor vs. Pattern Matching

Moderatoren: pmueller, SE - Design and Construction

AizazZaidee
BASIC-Programmierer
Beiträge: 106
Registriert: 20. Apr 2016 22:49

### Exam Question: Visitor vs. Pattern Matching

In Scala, pattern matching can be used to more elegantly model simple visitor patterns. In this task you are supposed to
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: 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 {
println(testExpr.accept(new FormatVisitor()))
println(testExpr.accept(new EvalVisitor(Map("x" -> 7))))
}
Any can help me fix my solution please ?

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
impl.format(testExpr, null)
}

emod02
Neuling
Beiträge: 9
Registriert: 27. Apr 2018 19:35

### Re: Exam Question: Visitor vs. Pattern Matching

Actually I don't know what's your problem, but down here is my solution to this task:

Code for the "visitor"

Code: Alles auswählen

object MatchVisitor {
def eval(expr: Expr, env: Map[String, Int]): Int = {
expr match {
case e: Constant =>
return e.value

case e: Var =>
return env(e.name)

return eval(e.left, env) + eval(e.right, env)

case e: Mul =>
return eval(e.left, env) * eval(e.right, env)
}
}

def format(expr: Expr): String = {
expr match {
case e: Constant =>
return e.value.toString

case e: Var =>
return e.name

return s"(${format(e.left)} +${format(e.right)})"

case e: Mul =>
return s"(${format(e.left)} *${format(e.right)})"
}
}
}

Code to call the "Visistor"

Code: Alles auswählen

object MatchingTest extends App {
val testExpr = Add(Mul(Constant(2), Var("x")), Constant(5))
println(MatchVisitor.format(testExpr))
println(MatchVisitor.eval(testExpr, Map("x" -> 7)))
}