SCHEMEのdo文の動きを検証してみる
先日のこちらのエントリー。
2012-06-28 - 氏家備忘録/非実用日記群
気になって夜も眠れません(懐かしい響きだが、単なる常套句)。
そこで、do文がどうlambda式に展開されるか、自分なりに妄想してみました。
do文
(do ((v1 init1 next1) ... (vn initn nextn)) (p r) body)
こんな感じでdo文は書きますよね。
これを少し変形してみます。
named-letに変換してみる。
(let loop ((v1 init1) ... (vn initn)) (if p r (begin body (loop next1 ... nextn))))
loopというダミーのシンボルをつかってループさせます。
lambda文に落とし込んでみる。
再起させる必要があるので、ちゃんとlambdaだけで書くとすればちょっと面倒だけど、set!を使ってごまかす。
((lambda (loop) (set! loop (lambda (v1 ... vn) (if p r (begin body (loop next1 ... nextn))))) (loop init1 ... initn)) '())
loopシンボルをとりあえず作って、あとからlambdaクロージャをset!してやる。
ちゃんと書こうとするとY-Combinatorだかなんだか使うんだよね確か(うろ覚え)。
件のdo文の例はどうなるの?
(do ((x 0 (+ x 1)) (r '() (lambda () x))) ((= x 1) (r)) )
ってな式だったから、上の変形に合わせてやれば次の通りlambdaに落とし込める。
((lambda (loop) (set! loop (lambda (x r) (if (= x 1) (r) (begin (loop (+ x 1) (lambda () x)))))) (loop 0 '())) '())
とりあえず動きそう。
自作のSCHEMEON.jsでは果たしてどうなるか!
少しずつちまちまと改良しているSCHEMEON.js。
do文の例そのままだと誤った答えを返してくれるが、lambdaに落とし込んだ例だとちゃんと帰ってくれるはず!
((lambda (loop) (set! loop (lambda (x r) (if (= x 1) (r) (begin (loop (+ x 1) (lambda () x)))))) (loop 0 '())) '()) -> 0
おお、ちゃんと0を返してくれた。よしよし。
根っこが間違っているわけではなさそうだなSCHEMEON.js。
do文をあとで手直しします。いつかいつの日か。