- 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 件のコメント:
コメントを投稿