hiroshi-manabe様の日本語訳を使わせてもらいます。
練習問題等はGaucheで実行。
リストに対するマップ
リストの全要素に指定した係数を掛けるという手続き。
_.scm
(define nil ())
(define (scale-list items factor)
(if (null? items)
nil
(cons (* (car items) factor)
(scale-list (cdr items) factor))))
_.scm
gosh> (scale-list (list 1 2 3 4 5) 10)
(10 20 30 40 50)
リストの全要素に何かをする、という抽象的な手続きmap
を作ってみよう。
_.scm
(define (map proc items)
(if (null? items)
nil
(cons (proc (car items))
(map proc (cdr items)))))
map
を使えば、scale-list
手続きは次のように書き直せる。
_.scm
(define (scale-list items factor)
(map (lambda (x) (* x factor)) items))
練習問題2.21
リストの要素を2乗する手続きを作ろう。まずはmap
を使わずに。
_.scm
(define (square-list1 items)
(if (null? items)
nil
(cons (square (car items)) (square-list (cdr items)))))
続いて、map
を使う方法。
_.scm
(define (square-list2 items)
(map (lambda (x) (square x)) items))
動かしてみよう。
_.scm
gosh> (square-list1 (list 1 2 3 4 5))
(1 4 9 16 25)
gosh> (square-list2 (list 1 2 3 4 5))
(1 4 9 16 25)
練習問題 2.22
square-lit
手続きを反復プロセス化したつもり。
_.scm
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons (square (car things)) answer))))
(iter items nil))
動かしてみよう・・・あれれ?
_.scm
gosh> (square-list (list 1 2 3))
(9 4 1)
逆になるのも当然だ。次のように結果のリストが作られるからだ。
_.scm
> (cons (square 1) nil) => (1)
> (cons (square 2) '(1)) => (4 1)
> (cons (square 3) '(4 1)) => (9 4 1)
ならば、こうだ。cons
の引数を逆にしてみる。
_.scm
(define (square-list-fix items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons answer (square (car things))))))
(iter items nil))
動かしてみよう。
_.scm
gosh> (square-list-fix (list 1 2 3))
(((() . 1) . 4) . 9)
ダメかー。そりゃそうだ。次のことが行われる。
_.scm
> (cons nil (square 1)) => (() . 1)
> (cons '(() . 1) (square 2)) => ((() . 1) . 4)
> (cons '((() . 1) . 4) (square 3)) => (((() . 1) . 4) . 9)
練習問題 2.23
手続きをそれぞれの要素に適用していくだけの手続きfor-each
を作ろう。begin
使ってもいいよね・・・
_.scm
(define (for-each proc items)
(if (null? items)
#t
(begin
(proc (car items))
(for-each proc (cdr items)))))
実行結果。
_.scm
gosh> (for-each
(lambda (x) (newline) (display x))
(list 57 321 88))
57
321
88#t