Skip to content

Instantly share code, notes, and snippets.

@halcat0x15a
Created January 10, 2016 06:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save halcat0x15a/a03e74040726e1f69606 to your computer and use it in GitHub Desktop.
Save halcat0x15a/a03e74040726e1f69606 to your computer and use it in GitHub Desktop.
import scala.annotation.tailrec
sealed abstract class Var {
def walk(subst: Subst): Var = {
@tailrec
def go(v: Var, stack: List[Var], acc: Option[Var]): Var =
v match {
case Unbound(k) =>
subst.get(k) match {
case None => acc.fold(v)(u => Cons(u, v))
case Some(v) => go(v, stack, acc)
}
case Cons(h, t) =>
go(h, t :: stack, acc)
case _ =>
stack match {
case Nil => acc.fold(v)(u => Cons(u, v))
case x :: xs => go(x, xs, acc.map(u => Cons(u, v)).orElse(Some(v)))
}
}
go(this, Nil, None)
}
}
case class Bound(value: Any) extends Var
case class Unbound(id: Long) extends Var
case class Cons(head: Var, tail: Var) extends Var
@lyricallogical
Copy link

      case Cons(h, t) => go(self)(h, h => self(t, t => Cons(h, t)))

継続内の self は普通にメソッド呼び出しするのでスタック深くなっちゃうけど、そんな大量に Cons ないでしょ、というつもりで、とりあえず他の箇所は goto になるようにコンパイラを言いくるめました。
Cons だらけだと普通にスタックあふれます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment