この小節(2.2.3)では、モジュールの構成法、可読性のためにとても大事なことを言っていて、いわく信号処理のように、独立したブロックとして考えなさいって言っている。
プログラムを組むときには当たり前の話ですけど、副作用のない関数型言語であれば、かなり厳密に守れるのかもしれません。
今日の課題はその構成要素となれるのを組むこと。
(define (accumulate op initial sequence) (if (null? sequence) initial (op (car sequence) (accumulate op initial (cdr sequence)))))
accumulateを使って、まずmapを作る。mapはリストの各要素に対して関数を適用した結果を返す関数です。たいていの言語には用意されてて、gaucheにも用意されているけど、自作するみたい。
(define (map p sequence) (accumulate (lambda (x y) (cons (p x) y)) () sequence))
こんな感じの関数です。
gosh> (map square (list 1 2 3 4 5)) (1 4 9 16 25)
appendは2つのリストを連結します。
(define (append seq1 seq2) (accumulate cons seq2 seq1))
すげーすっきりしてる。こんな感じの実行結果ですね。
gosh> (append (list 1 2 3) (list 4 5 6)) (1 2 3 4 5 6)
lengthはリストの長さを返すシンプルな関数ですけど、他に比べるとちょびっと複雑になった。
(define (length sequence) (accumulate (lambda (x y) (if (null? x) (+ 0 y) (+ 1 y))) 0 sequence))
こうなります。
gosh> (length (list 1 2 3 4)) 4