Поскольку я определяю переводчик с большим количеством переменных, я пишу это:Scala парциальных хвостовая рекурсия
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)
}
Для очень длинных выражений это не удается из-за StackOverflowException
, для выражений типа:
Let("a", 1,
Let("b", Plus("a", "a"),
Let("c", Plus("b", "a"),
Let("d", 1, ... )
Однако, как только значение переменной определено, мне просто нужно снова вызвать оценщика на тело Let
, мне кажется, что он должен просто выполнить некоторую частичную рекурсию хвоста.
Как можно добиться частичной рекурсии хвоста в Scala?
http://blog.higher-order.com/blog/2015/06/18/easy-performance-wins-with-scalaz/ –
Не выражается выражение 'eval (a) + eval (b) 'предотвратить рекурсию хвоста? Стек должен поддерживаться так, чтобы 'eval (b)' можно было оценить после завершения 'eval (a)'? Рекурсия хвоста возможна только тогда, когда возвращаемое значение является вызовом _single_ для рекурсивной функции. – Max
Очевидно. Вот почему у меня нет хвостовой рекурсии. Однако посмотрите, в случае, когда у меня просто много «давайте, я не хочу держать стек, я бы хотел использовать функцию, подобную хвостовой рекурсии». Частичная рекурсия хвоста. Репликация хвоста на частях, которые могут быть возвращены хвостом, и увеличить размер стека для других. –