Implementing Recursion

기존 방식 : with와 func를 사용한 재귀 표현 :: 복잡
새로운 방식(rec) : 간단 :: interpreter를 새롭게 update해야함.
developer들의 선택은??
abstract syntax
trait Expr
case class Num(n: Int) extends Expr
case class Add(lhs: Expr, rhs: Expr) extends Expr
case class Sub(lhs: Expr, rhs: Expr) extends Expr
case class Id(name: String) extends Expr
case class Fun(param: Id, body: Expr) extends Expr
case class App(funExpr: Expr, argExpr: Expr) extends Expr
case class If0(testExpr: Expr, thenExpr: Expr, elseExpr: Expr) extends Expr
case class Rec(fname: Id, namedExpr: Expr, fstCall: Expr) extends Expr
위의 abstract syntax는 데이터 구조에 불과함. 이를 실제로 해석/실행/정의하는 것은 interpreter에서 처리함.
// interp : Expr DefrdSub -> ExprValue
def interp(expr: Expr, ds: DefrdSub): ExprValue = expr match {
case Num(n) => NumV(n)
case Add(l, r) => numAdd(interp(l, ds), interp(r, ds))
case Sub(l, r) => numSub(interp(l, ds), interp(r, ds))
case Mul(l, r) => numMul(interp(l, ds), interp(r, ds))
case Id(name) => lookup(Id(name), ds)
case Fun(param, body) => ClosureV(param, body, ds)
case App(f a) =>
val fVal = interp(f ds)
val aVal = ExprValue(a, ds, None)
fVal match {
case ClosureV(param, body, closureDs) => interp(body, ASub(param, aVal, closureDs))
case _ => throw new Exception(“Expected a function”)
}
case If0(testExpr, thenExpr, elseExpr) => …
case Rec(fname, namedExpr, fstCall) => …
}
기존에 우리는 App까지 배움. 좀 낯선 App 복습 좀 하자면..?