2008年12月27日土曜日

【PAIP】22 Scheme: An Uncommon Lisp (その2)


  • 22.4 Throw, Catch, and Call/cc
  • 末尾再帰によって、loopはすべて記述できる。gotoを排除できるし、言語もシンプルになるよ。
  • しかしloop以外にもnonlocalなexitをしたい局面もあるよ。
  • CLではcatchとthrowがあるよ。
  • Schemeではcall-with-current-continuation(call/cc)という汎用かつ強力なものがあるよ。
  • call/ccはprocedureだよ。

  • call/ccの引数はひとつ。引数をcomputationと呼ぶ。
  • computiationはprocedureであり、これの引数もひとつ。
  • call/ccの返却値は、computationの返却値。
  • ただし、computationの引数(ccと呼ぶ)もprocedureであり、それはcurrent continuation pointを表わしている。
  • なので、

    (+ 1 (call/cc (lambda (cc) (+ 20 30))))
    は、ccが
    (lambda (val) (+ 1 val))
    であり、これがcomputationに渡されるが、computationはccを使っていないので、元の式は、
    ((lambda (val) (+ 1 val)) (+ 20 30))
    となり、231が値となる。

    (+ 1 (call/cc (lambda (cc) (+ 20 (cc 300)))))
    は、ccが
    (lambda (val) (+ 1 val))
    であり、これがcomputaionに渡される。computationはccを使っているので、使っているところでccの処理が接ぎ木される。
    ((lambda (val) (+ 1 val)) 300)
    なので値は301。また、次と同値とも言える。
    ((lambda (val) (+ 1 val))
    (catch 'cc
    ((lambda (v) (+ 20 v))
    (throw 'cc 300))))

  • というのが基本。で、ccという形で残りの計算をprocedureとして扱えるので、いろいろできる、と。
  • 特徴的なのは、catch, throwは動的エクステントだが、call/ccの継続は不定エクステントということ。

  • call/ccで、自動バックトラッキングを実装できるよ。おお、すごい。

  • 22.5 An Interpreter Supporting Call/cc
  • CPSでinterpをごりごり書き直す。

うーん。もともとSchemeを知っていたからなのかわからないが、インタプリタを書くことによってどれくらいLispに詳しくなるのかわからんなぁ。もちろんCLでインタプリタを書く方法には詳しくなるんだけど。
こつこつ。

0 件のコメント: