プログラミング再入門

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

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

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

ノート:

subst、subst2

関数substを解釈すると

  1. 新しいアトムnew、古いアトムold、リストを要素として含まないリストlatに適用し、「latと同じ要素からなるが最左のoldがnewに入れ替わったリスト」を意味する。
  2. そのリストは:
  3. latが空リストであれば、空リスト
  4. latの先頭要素がoldと同じであれば、newとlatの残り要素を繋いだリスト
  5. そうでなければ、latの先頭要素とlatの残りリストのoldをnewに入れ替えたリストを繋いだリスト

substの動作を確認する。

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

関数subst2を解釈すると

  1. 新しいアトムnew、古いアトムo1、古いアトムo2、リストを要素として含まないリストlatに適用し、「latと同じ要素からなるがo1かo2のどちらか最左の要素がnewに入れ替わったリスト」を意味する。
  2. そのリストは:
  3. latが空リストであれば、空リスト
  4. latの先頭要素がo1と同じであれば、newとlatの残り要素を繋いだリスト
  5. latの先頭要素がo2と同じであれば、newとlatの残り要素を繋いだリスト
  6. そうでなければ、latの先頭要素とlatの残りリストのo1かo2をnewに入れ替えたリストを繋いだリスト

subst2の動作を確認する。

> (let ((new 'vanilla)
        (o1 'chocolate)
        (o2 'banana)
        (lat '(banana ice cream with chocolate topping)))
    (subst2 new o1 o2 lat))
(vanilla ice cream with chocolate topping)
> 

orを使った実装

(define subst2
  (lambda (new o1 o2 lat)
    (cond
      ((null? lat) (quote ()))
      (else
       (cond
         ((or (eq? o1 (car lat))(eq? o2 (car lat)))
          (cons new (cdr lat)))
         (else
          (cons (car lat) (subst2 new o1 o2 (cdr lat)))))))))

動作を確認する。

> (let ((new 'vanilla)
        (o1 'chocolate)
        (o2 'banana)
        (lat '(banana ice cream with chocolate topping)))
    (subst2 new o1 o2 lat))
(vanilla ice cream with chocolate topping)
> 
multirember

multiremberの定義を解釈すると:

  1. アトムaとリストを要素として含まないリストlatに適用し、「latの要素のうちaではない要素からなるリスト」を意味する
  2. そのリストは
  3. latが空リストの場合、空リスト
  4. latの先頭要素がaと同じ場合、latの残りのリストからaを全て除いたリスト
  5. そうでない場合、latの先頭要素にlatの残りのリストからaを全て除いたリストを繋いだリスト

動作を確認する

> (let ((a 'cup)
        (lat '(coffee cup tea cup and hick cup)))
    (multirember a lat))
(coffee tea and hick)
> 

ここでも『teaをセーブして』『andをセーブして』『hickをセーブして』と言う表現には違和感がある。

multiinsertR、multiinsertL、multisubst

multiinsertRの動作を確認する。

> (let ((new '<-)
        (old 'cup)
        (lat '(coffee cup tea cup and hick cup)))
    (multiinsertR new old lat))
(coffee cup <- tea cup <- and hick cup <-)
> 

最初のmultiinsertLの定義が無限ループする事は確認出来るが、結果をここに貼ってもあまり意味は無い。

> (let ((new 'fried)
        (old 'fish)
        (lat '(chips and fish or fish and fried)))
    (multiinsertL new old lat))

Interactions disabled

修正されたmultiinsertLの定義の動作を確認する。

> (let ((new 'fried)
        (old 'fish)
        (lat '(chips and fish or fish and fried)))
    (multiinsertL new old lat))
(chips and fried fish or fried fish and fried)
> 

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

> (let ((new 'crab)
        (old 'fish)
        (lat '(chips and fish or fish and fried)))
    (multisubst new old lat))
(chips and crab or crab and fried)
>