リストの上で集合っぽい演算

30分プログラム、その674。リストの上で集合っぽい演算を定義してみました。
みなさん、知ってます? Rubyって配列を集合みたいに扱えるんです。

>> [1,2,3] - [3,4,5]
=> [1, 2]

[1,2,3] & [3,4,5]
=> [3]

>> [1,2,3] | [3,4,5]
=> [1, 2, 3, 4, 5]

ホントの集合とは違って、もとの配列内での順番が保存されるので、わりと便利だったりします。

というわけで、こんな感じの演算を作ってみましょう。SICP2.3.3で似たことをやっていた気がします。

使い方

(list-sub '(1 2 3) '(3 4 5))
(1 2)

gosh> (list-intersect '(1 2 3) '(3 4 5))
(3)

gosh> (list-union '(1 2 3) '(3 4 5))
(1 2 3 4 5)

ソースコード

#! /opt/local/bin/gosh
;; -*- mode:scheme; coding:utf-8 -*-
;;
;; list-set.scm -
;;
;; Copyright(C) 2009 by mzp
;; Author: MIZUNO Hiroki / mzpppp at gmail dot com
;; http://howdyworld.org
;;
;; Timestamp: 2009/10/08 21:02:20
;;
;; This program is free software; you can redistribute it and/or
;; modify it under MIT Lincence.
;;
(use srfi-1)

(define (mem? x xs eq)
  (find (cut eq <> x) xs))

(define (list-intersect xs ys . args)
  (let-optionals* args [(eq eq?)]
     (filter (cut mem? <> ys eq)
	     xs)))

(define (list-sub xs ys . args)
  (let-optionals* args [(eq eq?)]
     (filter (lambda(x) (not (mem? x ys eq)))
	     xs)))

(define (list-union xs ys)
  (append xs ys))