Unlambda on Scala

まめめもさんの Unlambda インタプリタを書いてみた - まめめも よりも綺麗な実装を書こうとしたら、等価なものができてしまいました。(^^; Scala で callcc はできるのでしょうか?

実装のコツとしては、遅延評価は後回しにするといいです。今、組み込み関数で外だしされているのは、vしか残っていませんが、最初は、全部外出しにしていました。` と . の2つから作っていき、eval()を作るよりも先に、「Unlambda ソース -> 自分の記述する言語のソース」を手作業で変換をかけてみると、どうやって実装するといいか、見えてきます。

関数型言語の処理系の実装の題材としては、非常にいい題材だと思います。

object Unlambda extends Application {
  // 表記を短縮するための型
  type a = Any
  type f = a => a
  // 1行分読み込む
  val line = new scala.collection.mutable.Queue[String]
  line ++= readLine.split("").drop(1).filter(_ != " ")
  // 組み込み関数 v
  def v(x:a):f = v _
  // 式の評価
  def eval():() => a = {
    val c = line.dequeue
    c match {
      case "`" => val f1 = eval
                  val f2 = eval
                  () => {
                    val f3 = f1()
                    if(f3 != None) f3.asInstanceOf[f](f2()) // 先行評価
                    else (x:a) => (f2()).asInstanceOf[f](x) // 遅延評価
                  }
      case "." => val x = line.dequeue; () => (y:a) => { print(x); y }
      case "e" => () => (x:a) => exit
      case "i" => () => (x:a) => x
      case "k" => () => (x:a) => (y:a) => x
      case "r" => () => (x:a) => { println; x }
      case "s" => () => (x:a=>f) => (y:f) => (z:a) => (x(z))(y(z))
      case "d" => () => None
      case "v" => () => v _
      case _   => () => c
    }
  }
  eval
}