よーしパパ、関数に名前を付けずに再帰させちゃうぞぉ!(その6)
- L
mk-lengthがmk-lengthに渡されたってことは、さらに再帰させるために引数を使うことができるのかな?
- R
そうさ。
mk-lengthを一回使えばlength1ができるよ。((lambda (mk-length) (mk-length mk-length)) (lambda (mk-length) (lambda (l) (cond ((null? l) 0) (else (+ 1 ((mk-length eternity) (cdr l))))))))
- L
(((lambda (mk-length) (mk-length mk-length)) (lambda (mk-length) (lambda (l) (cond ((null? l) 0) (else (+ 1 ((mk-length eternity) (cdr l)))))))) '(apples))の値は何になる?
- R
こりゃいい訓練になるね。紙と鉛筆でやってみよう。
だそうだ。
いきなりこれをやっていくのは自分は無理。
「どういう関数が出来上がるか」ってのが重要だと思うので、'(apples)は置いておく。
((lambda (mk-length) (mk-length mk-length)) (lambda (mk-length) ;←ココ (lambda (l) (cond ((null? l) 0) (else (+ 1 ((mk-length eternity) (cdr l))))))))
コメントの行から始まる無名関数をfと名付けると
(f f)
という格好をしている。
((lambda (mk-length) (lambda (l) (cond ((null? l) 0) (else (+ 1 ((mk-length eternity) (cdr l))))))) (lambda (mk-length) (lambda (l) (cond ((null? l) 0) (else (+ 1 ((mk-length eternity) (cdr l))))))))
相変わらずスムーズにできん。(いや、やらなくてもいいのかもしれないけど)
さらに、
(lambda (l) (cond ((null? l) (else (+ 1 (((lambda (mk-length) (lambda (l) (cond ((null? l) 0) (else (+ 1 ((mk-length eternity) (cdr l))))))) eternity) (cdr l))))))
ついでに、mk-lengthを消そう
(lambda (l) (cond ((null? l) (else (+ 1 ((lambda (l) (cond ((null? l) 0) (else (+ 1 ((eternity eternity) (cdr l)))))) (cdr l))))))
よし、これで考えやすくなった!
...って、これでいいのかな。再帰を考える練習になってないような。
書き直さずに、'(apple)を渡してどうなるか考えないと意味がないかな...?
この問題、1ステップずつ解説してないし。
前みたいにやさしく教えてよ。出会った頃のように。
最近のあなた、変わっちゃったわ!
今まではある関数をある関数に繰り返し適用していくことで再帰呼び出ししようとしてた。
((lambda (f) (f f)) g)
とか
((lambda (f) (f (f f))) g)
みたいに。だけど今度は違う。
gの中でも引数(関数)を評価することで再帰できる回数を1回分増やした感じ?
しかも、eternityを渡してるから「エラーで止まる」って挙動はなくなって、ちゃんと止まらなくなってくれた。
静的型付け言語ではコンパイルエラーとして取りだされるような「型の不整合によるエラー」で止まっていたのが、ちゃんと噛み合って動きだした感じ?
あー、難しい。