SICPを読む(97) 問題 3.8 - 命令プログラミングの落とし穴
問題を読み取れているのかわからない。
問題 3.8
最初に関数が呼ばれたのであれば、その値を返す。二度目以降なら0を返す。という関数にしてみた。
(define f (let ((flag #f)) (lambda (n) (if flag 0 (begin (set! flag #t) n)))))
フラグが立っていなければ、値を返し、フラグが立っていたらゼロを返す。
右から評価が出来ないので、fを入れ替えてテストした。
(+ (f 0) (f 1)) ; 0 ; fを再定義 (+ (f 1) (f 0)) ; 1
SICPと問題共有できてるのかな・・・。
回答を探索してみると色々あって面白い。
- 掛け算法
- 初期値を1として前回のと掛け算。
- 1 * 0 + 0 * 1 = 0, 1 * 1 + 1 * 0
- なるほど。うまいな。
- 前回の値を返す
- 初期値を0としておいて、
- (f 0) + (f 1) = 0 + 0, (f 1) + (f 0) = 0 + 1
- うまくいく。
色々解釈できるようだ。
足し算の方は遅延評価を使って評価を遅らせる方法もあると。
やってみよう。
(define (my-apply f method . args) (apply f (map (lambda (f) (f)) (if (eq? method 'reverse) (reverse args) args)))) ; リセットして (my-apply + 'normal (lambda () (f 0)) (lambda () (f 1))) ; 0 ; リセットして (my-apply + 'reverse (lambda () (f 0)) (lambda () (f 1))) ; 1
delayは使わず、lambdaで実装してみた。遅延評価とか理解してないけど、lambdaで囲めば評価を遅らせることが出来るよね。