Exam Question: Visitor vs. Pattern Matching

Moderatoren: pmueller, SE - Design and Construction

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

Exam Question: Visitor vs. Pattern Matching

Beitrag von AizazZaidee » 14. Jul 2018 14:08

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: 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))))
}
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
  val testExpr = Add(Mul(Constant(2),Var("x")), Constant(5))
  impl.format(testExpr, null)
}

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

Re: Exam Question: Visitor vs. Pattern Matching

Beitrag von emod02 » 14. Jul 2018 14:35

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)

      case e: Add =>
        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

      case e: Add =>
        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)))
}

Antworten

Zurück zu „Software Engineering - Design and Construction“