Here is the code:
trait Simplifier {
def caseNum(t: Num) = {
t.value
}
def caseMul(t: Mul) = {
t.right.simplify(this) * t.left.simplify(this)
}
def caseVar(t: Var) = {
t.assigned.simplify(this)
}
}
trait Expr {
def simplify(s: Simplifier): Int
}
class Num(val value: Int) extends Expr {
def simplify(s: Simplifier) = {
s.caseNum(this)
}
}
class Var(val assigned: Expr) extends Expr {
def simplify(s: Simplifier) = {
s.caseVar(this)
}
}
class Mul(val left: Expr, val right: Expr) extends Expr {
def simplify(s: Simplifier) = {
s.caseMul(this)
}
}
If you paste this into the repl, you will get
<console>:11: error: not found: type Num
def caseNum(t: Num) = {
^
<console>:14: error: not found: type Mul
def caseMul(t: Mul) = {
^
<console>:17: error: not found: type Var
def caseVar(t: Var) = {
^
If you change the order of definitions, you still will get similar errors.
If you use :paste
at the REPL this compiles fine. Without the :paste
command, the evaluation is happening immediately, the classes that are not yet defined cannot be seen so it fails. In paste mode, they are compiled together.
See below:
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Simplifier {
def caseNum(t: Num) = {
t.value
}
def caseMul(t: Mul) = {
t.right.simplify(this) * t.left.simplify(this)
}
def caseVar(t: Var) = {
t.assigned.simplify(this)
}
}
trait Expr {
def simplify(s: Simplifier): Int
}
class Num(val value: Int) extends Expr {
def simplify(s: Simplifier) = {
s.caseNum(this)
}
}
class Var(val assigned: Expr) extends Expr {
def simplify(s: Simplifier) = {
s.caseVar(this)
}
}
class Mul(val left: Expr, val right: Expr) extends Expr {
def simplify(s: Simplifier) = {
s.caseMul(this)
}
}
// Exiting paste mode, now interpreting.
defined trait Simplifier
defined trait Expr
defined class Num
defined class Var
defined class Mul
An alternative to using the :paste
command, is manually wrapping your code in a wrapper object.
scala> object Wrapper {
| trait Simplifier {
| def caseNum(t: Num) = {
| t.value
| }
| def caseMul(t: Mul) = {
| t.right.simplify(this) * t.left.simplify(this)
| }
| def caseVar(t: Var) = {
| t.assigned.simplify(this)
| }
| }
|
| trait Expr {
| def simplify(s: Simplifier): Int
| }
|
| class Num(val value: Int) extends Expr {
| def simplify(s: Simplifier) = {
| s.caseNum(this)
| }
| }
|
| class Var(val assigned: Expr) extends Expr {
| def simplify(s: Simplifier) = {
| s.caseVar(this)
| }
| }
|
| class Mul(val left: Expr, val right: Expr) extends Expr {
| def simplify(s: Simplifier) = {
| s.caseMul(this)
| }
| }
| }
defined module Wrapper
scala> import Wrapper._
import Wrapper._