Scheme修行のtryについて
- 作者: Daniel P. Friedman and Matthias Felleisen,元吉文男,横山晶一
- 出版社/メーカー: オーム社
- 発売日: 2011/06/15
- メディア: 単行本(ソフトカバー)
- 購入: 3人 クリック: 46回
- この商品を含むブログ (10件) を見る
p89の欄外で補足されているtryについて.
これが出てきたのは rember1*
の実装の中です.
rember1*
はatom aとリストlを引数に取ります.
lの中で最初に出てきたaと同じアトムを削除して新しいリストを返す手続きです.
tryを使う前の実装は以下になります.
(define rember1* (lambda (a l) (if (atom? (let/cc oh (rm a l oh))) l (rm a l (quote ()))))) (define rm (lambda (a l oh) (cond ((null? l) (oh (quote no))) ((atom? (car l)) (if (eq? (car l) a) (cdr l) (cons (car l) (rm a (cdr l) oh)))) (else (let ((new-car (let/cc oh (rm a (car l) oh)))) (if (atom? new-car) (cons (car l) (rm a (cdr l) oh)) (cons new-car (cdr l))))))))
リストの中で最後まで探し終わってlがnullになれば継続に(quote no)
を渡します.
atomであればcarにリストはないのでcdrを探します.
再帰的に探して,aと同じものがあれば,それを取り除いた残りのリストを返します.
取り除くのは最初に見つかったものだけです.
このコードをtryを使うとこうなります.
(define rember1* (lambda (a l) (try oh (rm a l oh) l))) (define rm (lambda (a l oh) (cond ((null? l) (oh (quote no))) ((atom? (car l)) (if (eq? (car l) a) (cdr l) (cons (car l) (rm a (cdr l) oh)))) (else (try oh2 (cons (rm a (car l) oh2) (cdr l)) (cons (car l) (rm a (cdr l) oh)))))))
tryについてはここでページ欄外に
(try x α β) = (let/cc success (let/cc x (success a)) b)
と書かれています.
ここがなかなかわかりませんでした.
まず中のlet/ccから考えます.
(let/cc x (success α))
α内で継続xが使われているはずです.
継続xに値γが渡されると,(let/cc x γ)
となり,次の計算βに進みます.
継続xに値が渡されない場合はαの値が継続successに渡され,そこで計算が終了しこの式の値はαとなります.
つまり,tryはα内で継続xに値が渡されればβの値が返り,
渡されなければαの値が返るわけです.
元の式で継続に値が渡されたのを判別するために(quote no)
を継続に渡してatom?で判別していたものを
継続が返ってくるかこないかで判別できるようになっています.
継続難しいです.
でもScheme修行で少しずつわかってきた気がします.