Weil ich mit vielen Variablen einen Dolmetscher bin definiert, schreibe ich das:Scala Teil Endrekursion
type Context = Map[String, Int]
abstract class Expr
case class Let(varname: String, varvalue: Expr, body: Expr) extends Expr
case class Var(name: String) extends Expr
case class Plus(a: Expr, b: Expr) extends Expr
case class Num(i: Int) extends Expr
def eval(expr: Expr)(implicit ctx: Context): Int = expr match {
case Let(i, e, b) => eval(b)(ctx + (i -> eval(e)))
case Var(s) => ctx(s)
case Num(i) => i
case Plus(a, b) => eval(a) + eval(b)
}
Für sehr lange Ausdrücke versagt dies wegen StackOverflowException
, für Ausdrücke des Typs:
Sobald jedoch der Wert einer Variablen definiert ist, muss ich nur noch den Evaluator auf dem Körper der Let
aufrufen, es scheint mir, dass es nur eine Art partielle Tail-Rekursion tun sollte.
Wie ist es möglich, partielle Tail-Rekursion in Scala zu erreichen?
http://blog.higher-order.com/blog/2015/06/18/easy-performance-wins-with-scalaz/ –
Ist kein Ausdruck wie 'eval (a) + eval (b) 'verhindern Tail Rekursion? Der Stack muss beibehalten werden, damit das 'eval (b)' ausgewertet werden kann, nachdem das 'eval (a)' beendet ist? Die Tail-Rekursion ist nur möglich, wenn der zurückgegebene Wert ein _single_-Aufruf an die rekursive Funktion ist. – Max
Offensichtlich. Deshalb kann ich keine Schwanzrekursion haben. Allerdings, in dem Fall, ich habe gerade eine Menge 'Let's, ich möchte nicht den Stapel zu behalten, würde ich gerne die Funktion wie Tail-Recursion tun. Eine Art partielle Tail-Rekursion. Tail recurse auf die Teile, die tail-rekursiv sein können, und stapeln die Stack-Größe für andere. –