SICPを読む(49) 問題 2.21 - 2.23 mapの問題を解こう。

サクサク進む。これくらいの問題が続いてくれると嬉しいんだけど・・・。

問題 2.21

穴埋め問題。

(define (square x) (* x x))

(define (square-list items)
  (if (null? items)
      `()
      (cons (square (car items))
            (square-list (cdr items)))))

(square-list (list 1 2 3 4)) ; (1 4 9 16)

(define (square-list items)
  (map square items))

(square-list (list 1 2 3 4)) ; (1 4 9 16)

問題 2.22

反復にすると、逆順になる。何故か?

評価順序が逆になるから。traceで確認してみる。

再帰の場合、`()になったところからリストに追加している。

|(square-list (1 2 3 4))
| (square-list (2 3 4))
| |(square-list (3 4))
| | (square-list (4))
| | |(square-list ())
| | |()
| | (16)
| |(9 16)
| (4 9 16)
|(1 4 9 16)

反復の場合、順次リストに追加するので、うまくいかない。

|(iter (1 2 3 4) ())
|(iter (2 3 4) (1))
|(iter (3 4) (4 1))
|(iter (4) (9 4 1))
|(iter () (16 9 4 1))
|(16 9 4 1)

次のは、(cons list list)となってしまい、うまくいかない。
次のは、(cons list atom)となってしまい、うまくいかない。

反復で正順なリストを作るにはどうしたら良いのか・・・謎

追記

反復で正順なリストを作る方法はSICP memo: 問題2.22にあった。

append使ったら再帰してるのと変わらない気がするので、反復で正順なリストを作るのは得策では無い。

問題 2.23

for-eachを作る問題。

こうかな・・・。

(define (for-each proc items)
  (cond ((not (null? items))
         (proc (car items))
         (for-each proc (cdr items)))))

こう見るとfor-eachってセクシーさに欠けるな。

解答例を見てみたけど、(not (null? items))と書いてる人はいなかった。

#undefは返せないのかなぁ。返してないから#undefなんだけどさ・・・。

メモ

beginは複数の文をまとめる事ができる。最後の評価を返す。SICP P128

if文書くときに便利。

(if (= (random 2) 0)
    (begin
      (newline)
      (display "あたり"))
    (begin
      (newline)
      (display "ハズレ")))

手元に置いて、すぐに参照できるScheme本が欲しくなってきた。

選択肢は少ない・・・。