The Littile Schemer 8章"Lambda the Ultimate"読了
最後の関数、evens-only*&coも難しいです。
何がムズいって、(car l)がリストだった時の書き方かなぁ...。
要素が数字のみのネストしたリストlを受け取って、奇数だけ除去して返す関数evens-only*を継続渡しスタイルに書きなおす問題です。
参考までに、継続渡しじゃないevens-only*関数はこんな関数です。
(define evens-only* (lambda (l) (cond ((null? l) '()) ((atom? (car l)) (cond ((even? (car l)) (cons (car l) (evens-only* (cdr l)))) (else (evens-only* (cdr l))))) (else (cons (evens-only* (car l)) (evens-only* (cdr l)))))))
評価してみると、こんな感じです。
gosh> (define nums* '((1) 2 3 ((4) 5 ((6) 7 8) 9 ) 10)) nums* gosh> nums* ((1) 2 3 ((4) 5 ((6) 7 8) 9) 10) gosh> (evens-only* nums*) (() 2 ((4) ((6) 8)) 10)
これと同じ機能(奇数を除去する機能)を持ちつつ、同時に
- 出現したすべての偶数の積
- 出現したすべての奇数の和
を計算する機能を持つ関数evens-only*&coを継続渡しスタイルで書きなおすと...
(define evens-only*&co (lambda (l cont) (cond ((null? l) (cont '() 1 0)) ((atom? (car l)) (cond ((even? (car l)) (evens-only*&co (cdr l) (lambda (evens* prod sum) (cont (cons (car l) evens*) (* (car l) prod) sum)))) (else (evens-only*&co (cdr l) (lambda (evens* prod sum) (cont evens* prod (+ (car l) sum))))))) (else (evens-only*&co (car l) (lambda (al ap as) (evens-only*&co (cdr l) (lambda (dl dp ds) (cont (cons al dl) (* ap dp) (+ as ds))))))))))
(car l)にevens-only*&coを適用した結果、「偶数のみのリスト」「偶数の積」「奇数の和」が計算されるけど、
その結果に累積する形で(cdr l)に対するevens-only*&coの結果も持たなくてはいけないんですよね。
これをどう表現するか、僕にはとても難しいです。
でも、1回目読んだ時よりも、だいぶん理解できたんじゃないかと思う。