SICP §2.3.3(集合の表現 その1 [順序づけられないリストとしての集合])

さて、ここから先は集合の話になるぞと。
ざーっと読んでみたら結構なボリュームがあるし、内容的にもヘビーな感じを受ける。
なので、ペインタの二の舞にならんよう、セクションの内容をきっちり追っていきたいと思う。


最初は、「順序なし」「重複なし」の集合の表現について。
集合のオブジェクトはまんまリストを使うようですよ。
つまり、こういう性質の集合なら構成子は不要?(まぁ作ってもいいんだろう。。)
あ、ちなみに空集合は空リストだそうです。

じゃ、選択子や述語等で必要なものは何か。。こんな感じになるみたい。

union-set和集合(2つの集合のうち、どちらかの集合に現れる要素を含んでいる集合)を計算する。
intersection-set積集合(両方の集合に現れる要素だけを含む集合)を計算する。
element-of-set?与えられた要素が集合の構成要素であるかという述語。
adjoin-set引数としてオブジェクトと集合をとり、元の集合の要素と追加する要素を含む集合を返す。

さて、では各種手続きを実装してみましょうか。

(define (element-of-set? x set)
  (cond ((null? set)
	 #f)
	((equal? x (car set))
	 #t)
	(else
	 (element-of-set? x (cdr set)))))

(define (adjoin-set x set)
  (if (element-of-set? x set) ;重複する場合はまんまsetを返却
      set
      (cons x set)))

(define (intersection-set set1 set2)
  (cond ((or (null? set1) (null? set2))
	 '())
	((element-of-set? (car set1) set2) ;共通要素があったら返却用リストに追加。
	 (cons (car set1)                  ;そして被追加側は再帰。
	       (intersection-set (cdr set1) set2)))
	(else
	 (intersection-set (cdr set1) set2))))

;なんとなく反復で定義してみる。
(define (intersection-set set1 set2)
  (let loop ((ans '())
	     (s1 set1)
	     (s2 set2))
    (cond ((or (null? s1) (null? s2))
	   (reverse ans)) ;順序関係ないから reverse しなくてもいいけど、見やすいから。。
	  ((element-of-set? (car s1) s2)
	   (loop (cons (car s1) ans)
		 (cdr s1)
		 set2))
	  (else
	   (loop ans (cdr s1) s2)))))

残ってる union-set 手続きだけど、問題2.59で定義しろって書いてあるので次のエントリで。