Previous Up Next

3.10  リストの更新



Exercise 24  [難易度 2] setcar, setcdrというキーワードを追加し, Exercise 17 で導入したリスト構造の先頭要素(car)と後続部分 (cdr)の値を更新できるようにインタプリタを変更せよ. (注意: この問題 は, Exercise 18のようにリストをペア構造として扱う方が遥か に見通しがよいので, Exercise 18 を行なってから解答した方 がよい.)

setcar
は引数として二つの式をうけとり, 代入のように, 副作用として第一式が示すリストの先頭要素を第二式が示す値で置き換える. 同様に, setcdrは引数として二つの式をうけとり, 第一式が示すリストの後続要素を第二式が示すリストで置き換える. 返り値については特に限定しない (代入のときを参考にせよ).

⇒ (let ((xs (list 0 2 3 4)))
        (let ((d (setcar xs 1)))
             xs))
(1 2 3 4)
⇒ (let ((xs (list 0 1 3 4)))
        (let ((d (setcdr (cdr xs) (list 2 3 4))))
             xs))
(0 1 2 3 4)
setcar, setcdrは, Exercise 18のようにリストをペア構造としてみれば,

⇒ (let ((p (cons 0 2)))
        (let ((d (setcar p 1)))
             p))
(1 . 2)
⇒ (let ((p (list 0 1 2)))
        (let ((d (setcdr p 4)))
             p))
(0 . 4)
のように, それぞれペアの第一要素, 第二要素を置き換えるものとして実現できる. setcar, setcdrを用いたプログラムを書いてテストせよ.

⇒ (let ((xs (list 1 3 4 5)))
        (let ((d (setcdr xs (cons 2 (cdr xs)))))
             xs))
(1 2 3 4 5)
⇒(letrec ((nconc (lambda (xs ys)
                  (if (null xs) ys
                      (if (null (cdr xs)) (setcdr xs ys)
                          (nconc (cdr xs) ys))))))
  (let ((a (list 0 1 2))
        (b (list 3 4 5)))
    (let ((d (nconc a b)))
      a)))
(0 1 2 3 4 5)


Exercise 25  [難易度 2] 前問で導入したsetcdrを用いて,

⇒ (letseq ((xs (cons 1 ()))
               (d (setcdr xs xs)))
        xs)
というプログラムを実行すると,無限に要素1が続く無限リストが返るは ずである.これは, リストlのcdr部がl自身を参照するという,循 環参照が起こっているからである.このような循環参照による無限リストを 「何らかの(無限ループしない)手段で」表示できるようにCore.pp の定義を 工夫せよ.(どのくらい凝ったことをするかで難易度は大きく変わる.)



Previous Up Next