(defun set-equal (a b ) (cond ((null a) (null b)) ((member (car a) b) (set-equal (cdr a) (remove (car a) b))) (t nil)))このように定義できますが、 集合の要素が同じかどうかを 調べるための:test関数を与える形で定義すれば、
(defun set-equal (a b &key (test #'eql)) (cond ((null a) (null b)) ((member (car a) b :test test) (set-equal (cdr a) (remove (car a) b :test test) :test test)) (t nil)))互いに部分集合であるかどうか、あるいは、 排他的ORが空集合であれば等しい、ということであるので,
(defun set-equal (a b &key (test #'eql)) (and (subsetp a b) (subsetp b a))) (defun set-equal (a b &key (test #'eql)) (not (set-exclusive-or a b :test test)))としてもよいが,等しくない場合に,set-exclusive-or で無駄なデータが 作られるためにゴミを生みやすい定義になります.
> (set-equal '(a b c) '(b c)) NIL > (set-equal '(a b) '(b a c)) NIL > (set-equal '(a b) '(b a)) T > (set-equal nil nil) T > (set-equal nil '(a)) NIL > (set-equal '(a) nil) NIL > (set-equal '((a) (b)) '((b) (a))) NIL > (set-equal '((a) (b)) '((b) (a)) :test #'equal) T > (set-equal '(#\a #\b) '(#\B #\a)) NIL > (set-equal '(#\a #\b) '(#\B #\a) :test #'char-equal) Tこの:testに自分自身のset-equalを与えれば、 集合の集合同士が同じかどうかを調べることができるようになります。
USER(104): (set-equal '((a b) (c d)) '((d c) (b a))) NIL USER(105): (set-equal '((a b) (c d)) '((d c) (b a)) :test #'set-equal) T