プログラミング再入門

プログラミングをもう一度ちゃんと勉強する読書ノート

Scheme手習い 第3章 偉大なるCons(その2)

consを使った関数の続きです。

ノート:

firsts

関数firstsを解釈すると

  1. 空リストか空ではないリストを含むリストlに適用し、「要素としてのリスト各々の最初の要素だけからなるリスト」を意味する
  2. そのリストは:
  3. lが空リストの場合は空リストである
  4. lの最初の要素(これもリスト)の最初の要素に、lの残りのリストにfirstsを適用した結果を繋げたリストである

firstsの定義を評価してみる。

> (firsts '((a b) (c d) (e f)))
(a c e)
>

firstsとしては想定外の空リストあるいはアトムを含むリストの場合

> (firsts '((a b) () (e f)))
. . mcar: expects argument of type <mutable-pair>; given ()
> (firsts '((a b) (c d) e f))
. . mcar: expects argument of type <mutable-pair>; given e
> 

carが取れないのでエラーとなる。

secondsは一瞬出て来るが定義が出て来ないので作ってみる。

(define seconds
  (lambda (l)
    (cond
      ((null? l) '())
      (else
       (cons (car (cdr (car l))) (seconds (cdr l)))))))

lについては正しいリストが渡るものとし、特にエラーケースは考えない。

評価してみる。

> (seconds '((a b) (c d) (e f)))
(b d f)
>
insertR

insertの引数の名前としてnewは良いとして、oldは変ではないか?

関数insertRの最初の定義を解釈すると:

  1. アトムnewとoldと要素としてリストを含まないリストlatに適用し、「latと同じ要素を持つリストで最左のoldの次にnewが挿入された状態のリスト」を意味する(つもり)
  2. そのリストは:
  3. latが空リストの場合、空リストである
  4. latの先頭がoldと同じ場合、latの残りのリストである
  5. そうでない場合、latの先頭にlatの残りのリストのoldの右にnewを挿入した(つもりの)リストを繋いだリストである

この定義の動作を確認する。

> (let ((new 'topping)
        (old 'fudge)
        (lat '(ice cream with fudge for dessert)))
    (insertR new old lat))
(ice cream with for dessert)
> 

二番目の定義を解釈すると:

  1. アトムnewとoldと要素としてリストを含まないリストlatに適用し、「latと同じ要素を持つリストで最左のoldの次にnewが挿入された状態のリスト」を意味する(つもり)
  2. そのリストは:
  3. latが空リストの場合、空リストである
  4. latの先頭がoldと同じ場合、newとlatの残りのリストを繋いだリストである
  5. そうでない場合、latの先頭にlatの残りのリストのoldの右にnewを挿入した(つもりの)リストを繋いだリストである

この定義の動作を確認する。

> (let ((new 'topping)
        (old 'fudge)
        (lat '(ice cream with fudge for dessert)))
    (insertR new old lat))
(ice cream with topping for dessert)
> 

三番目の定義を解釈すると:

  1. アトムnewとoldと要素としてリストを含まないリストlatに適用し、「latと同じ要素を持つリストで最左のoldの次にnewが挿入された状態のリスト」を意味する
  2. そのリストは:
  3. latが空リストの場合、空リストである
  4. latの先頭がoldと同じ場合、oldとnewとlatの残りのリストを繋いだリストである
  5. そうでない場合、latの先頭にlatの残りのリストのoldの右にnewを挿入したリストを繋いだリストである

この定義の動作を確認する。

> (let ((new 'topping)
        (old 'fudge)
        (lat '(ice cream with fudge for dessert)))
    (insertR new old lat))
(ice cream with fudge topping for dessert)
> 

それまでに出て来た例も評価してみる。

> (let ((new 'jalape&#241;o)
        (old 'and)
        (lat '(tacos tamales and salad)))
    (insertR new old lat))
(tacos tamales and jalape&#241;o salad)
> (let ((new 'e)
        (old 'd)
        (lat '(a b c d f g d h)))
    (insertR new old lat))
(a b c d e f g d h)
> 
insertL

insertLは例が無いので、insertRと同じ引数で評価して比較してみる。

> (let ((new 'topping)
        (old 'fudge)
        (lat '(ice cream with fudge for dessert)))
    (insertL new old lat))
(ice cream with topping fudge for dessert)
> 

fudgeとtoppingの順番が入れ替わっている。