(defun union-rec (set1 set2)
( declare ( notinline union - rec ) ) 
  (cond ((null set1) set2)
        ((not (member (first set1) set2))
         (union-rec (rest set1) (cons (first set1) set2)))
        (t (union-rec (rest set1) set2))))

(defun intersection-rec-int (set1 set2 result)
  ;(declare (notinline intersection-rec-int))
  (cond ((or (null set1) (null set2)) result)
        ((and (member (first set1) set2)
              (not (member (first set1) result)))
         (intersection-rec-int (rest set1) set2 (cons (first set1) result)))
        ((and (member (first set2) set1)
              (not (member (first set2) result)))
         (intersection-rec-int set1 (rest set2) (cons (first set2) result)))
        (t (intersection-rec-int (rest set1) (rest set2) result))))

(defun intersection-rec (set1 set2)
  (intersection-rec-int set1 set2 nil))

(defun set-difference-rec (set1 set2)
  ;(declare (notinline set-difference-rec))
  (cond ((null set2) set1)
        ((member (first set2) set1)
         (set-difference-rec (remove (first set2) set1) (rest set2)))
        (t (set-difference-rec set1 (rest set2)))))

;;(trace union-rec)
;;(trace intersection-rec-int)
;;(trace set-difference-rec)

(let ((test1 '(union-rec '(a b c d e) '(a e i o)))
      (test2 '(intersection-rec '(a b c d e) '(a e i o)))
      (test3 '(set-difference-rec '(a b c d e) '(a e i o))))
  (format t "~s = ~s~%" test1 (eval test1))
  (format t "~s = ~s~%" test2 (eval test2))
  (format t "~s = ~s~%" test3 (eval test3)))

(declare (notinline intersection-rec-int))
(declare (notinline set-difference-rec))
(trace union-rec)
(trace intersection-rec-int)
(trace set-difference-rec)

(defun union-rec (set1 set2)
( declare ( notinline union - rec ) ) 
  (cond ((null set1) set2)
        ((not (member (first set1) set2))
         (union-rec (rest set1) (cons (first set1) set2)))
        (t (union-rec (rest set1) set2))))

(defun intersection-rec-int (set1 set2 result)
  (cond ((or (null set1) (null set2)) result)
        ((and (member (first set1) set2)
              (not (member (first set1) result)))
         (intersection-rec-int (rest set1) set2 (cons (first set1) result)))
        ((and (member (first set2) set1)
              (not (member (first set2) result)))
         (intersection-rec-int set1 (rest set2) (cons (first set2) result)))
        (t (intersection-rec-int (rest set1) (rest set2) result))))

(defun intersection-rec (set1 set2)
  (intersection-rec-int set1 set2 nil))

(defun set-difference-rec (set1 set2)
  (cond ((null set2) set1)
        ((member (first set2) set1)
         (set-difference-rec (remove (first set2) set1) (rest set2)))
        (t (set-difference-rec set1 (rest set2)))))


(let ((test1 '(union-rec '(a b c d e) '(a e i o)))
      (test2 '(intersection-rec '(a b c d e) '(a e i o)))
      (test3 '(set-difference-rec '(a b c d e) '(a e i o))))
  (format t "~s = ~s~%" test1 (eval test1))
  (format t "~s = ~s~%" test2 (eval test2))
  (format t "~s = ~s~%" test3 (eval test3)))
