;;; list-lib
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; xcons tree-copy make-list list-tabulate cons* list-copy 
;;; proper-list? dotted-list? circular-list? not-pair? end? 
;;; circular-list length+
;;; iota
;;; first second third fourth fifth sixth seventh eighth ninth tenth
;;; car+cdr
;;; take       drop       take!
;;; take-right drop-right drop-right!
;;; last last-pair
;;; zip unzip1 unzip2 unzip3 unzip4 unzip5
;;; append! reverse-append append-reverse!
;;; unfold unfold/tail foldl foldr pair-foldl pair-foldr reducel reducer
;;; append-map append-map! map! pair-for-each filter-map map-in-order
;;; filter  partition  remove
;;; filter! partition! remove! 
;;; find find-tail any every list-index
;;; del  delq  delv  delete 
;;; del! delq! delv! delete!
;;; mem ass alist-cons alist-copy
;;; delq-duplicates  delv-duplicates  delete-duplicates  del-duplicates 
;;; delq-duplicates! delv-duplicates! delete-duplicates! del-duplicates!
;;; alist-delete  del-ass  del-assq  del-assv  del-assoc
;;; alist-delete! del-ass! del-assq! del-assv! del-assoc!
;;; reverse!
;;;    
;;; cons pair? null? list? list length append reverse	    (These are the
;;; car cdr ... cdddar cddddr set-car! set-cdr! list-ref     R4RS procedures
;;; member memq memv assoc assq assv			     re-exported by
;;; map for-each					     list-lib.)

(define-interface list-lib-interface
  (export
   ;; xcons <cdr> <car>
   (xcons (proc (:value :value) :value))

   (tree-copy (proc (:value) :value))

   ;; make-list len [fill]
   (make-list (proc (:exact-integer &opt :value) :value))

   ;; list-tabulate elt-proc len
   (list-tabulate (proc (:exact-integer (proc (:exact-integer) :value)) :value))

   ;; cons* item ... 
   (cons* (proc (:value &rest :value) :value))

   ;; list-copy lis
   (list-copy (proc (:value) :value))

   (circular-list (proc (:value &opt :value) :pair))

;  ((:iota iota:)
;   (proc (:number &opt :number :number) :value))

   (iota (proc (:exact-integer &opt :number :number) :value))

   (proper-list?   (proc (:value) :boolean))
   (dotted-list?   (proc (:value) :boolean))
   (circular-list? (proc (:value) :boolean))

   (not-pair? (proc (:value) :boolean))
   (end?      (proc (:value) :boolean))

   ((first second third fourth fifth sixth seventh eighth ninth tenth)
    (proc (:pair) :value))

   (car+cdr (proc (:pair) (some-values :value :value)))

   ;; take  lis i	take-right  lis i
   ;; drop  lis i	drop-right  lis i
   ;; take! lis i	drop-right! lis i
   ((take drop take! take-right drop-right drop-right!)
    (proc (:value :exact-integer) :value))

   (last (proc (:pair) :value))

   (last-pair (proc (:pair) :pair))

   (zip    (proc (:value &rest :value) :value))
   (unzip1 (proc (:value) :value))
   (unzip2 (proc (:value) (some-values :value :value)))
   (unzip3 (proc (:value) (some-values :value :value :value)))
   (unzip4 (proc (:value) (some-values :value :value :value :value)))
   (unzip5 (proc (:value) (some-values :value :value :value :value :value)))

   (append! (proc (:value &rest :value) :value))

   ((append-reverse append-reverse!) (proc (:value :value) :value))

   (unfold (proc ((proc (:value) :boolean)
		  (proc (:value) :value)
		  (proc (:value) :value)
		  :value)
		 :value))

   (unfold/tail (proc ((proc (:value) :boolean)
		       (proc (:value) :value)
		       (proc (:value) :value)
		       (proc (:value) :value)
		       :value)
		      :value))

   ((foldl foldr)
    (proc ((proc (:value :value &rest :value) :value)
	   :value :value &rest :value)
	  :value))

   ((pair-foldl pair-foldr)
    (proc ((proc (:pair :value &rest :value) :value)
	   :value :value &rest :value)
	  :value))

   ((reducel reducer)
    (proc ((proc (:value :value) :value) :value :value) :value))

   ((append-map append-map! filter-map map! map-in-order)
    (proc ((proc (:value &rest :value) :value) :value &rest :value) :value))

   (pair-for-each (proc ((proc (:pair &rest :pair) :values) :value &rest :value)
			:unspecific))

   ((filter filter! remove remove!)
    (proc ((proc (:value) :boolean) :value) :value))

   ((partition partition!) (proc ((proc (:value) :boolean) :value)
				 (some-values :value :value)))
   ((find find-tail) (proc ((proc (:value) :boolean) :value) :value))

   ((any every)
    (proc ((proc (:value &rest :value) :value) :value &rest :value) :value))

   (list-index (proc ((proc (:value &rest :value) :value) :value &rest :value)
		     :value))

   ((del del!) (proc ((proc (:value :value) :boolean) :value :value) :value))
   ((delq delq!  delv delv!  delete delete!)
    (proc (:value :value) :value))
   (mem (proc ((proc (:value :value) :boolean) :value :value) :value))
   (ass (proc ((proc (:value :value) :boolean) :value :value) :value))
   (alist-cons (proc (:value :value :value) :value))
   (alist-copy (proc (:value) :value))

   ((delq-duplicates  delv-duplicates  delete-duplicates
     delq-duplicates! delv-duplicates! delete-duplicates!)
    (proc (:value) :value))

   ((del-duplicates del-duplicates!)
    (proc ((proc (:value) :value) :value) :value))

   ((alist-delete alist-delete!  del-ass del-ass!)
    (proc ((proc (:value :value) :value) :value :value) :value))
   ((del-assq del-assq!  del-assv del-assv!  del-assoc del-assoc!)
    (proc (:value :value) :value))
   (reverse! (proc (:value) :value))

   ;; R4RS exports
   (cons (proc (:value :value) :pair))
   ((pair? null? list?) (proc (:value) :boolean))
   (list-ref (proc (:value :exact-integer) :value))
   (list (proc (&rest :value) :value))
   (length (proc (:value) :exact-integer))
   (append (proc (&rest :value) :value))
   (reverse (proc (:value) :value))
   ((car cdr
     caaaar caaadr caadar caaddr caaar caadr caar
     cadaar cadadr caddar cadddr cadar caddr cadr
     cdaaar cdaadr cdadar cdaddr cdaar cdadr cdar
     cddaar cddadr cdddar cddddr cddar cdddr cddr) (proc (:value) :value))
   ((set-car! set-cdr!) (proc (:pair :value) :unspecific))
   ((member memq memv) (proc (:value :value) :value))
   ((assoc  assq assv) (proc (:value :value) :value))
   (map (proc ((proc (:value) :value) &rest :value) :value))
   (for-each (proc ((proc (:value) :values) &rest :value) :unspecific))
   ))


;;; lset-lib
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; lset<= = list1 list2 ...
;;; lset=  = list1 list2 ...
;;; lset-adjoin = list elt1 ...
;;; lset-union = list1 ...
;;; lset-intersection = list1 list2 ...
;;; lset-difference = list1 list2 ...
;;; lset-xor = list1 ...
;;; lset-diff+intersection = list1 list2 ...
;;; ... and their side effecting counterparts:
;;;   lset-union! lset-intersection! lset-difference! lset-xor! 
;;;   lset-diff+intersection!
;;;
;;; adjoin {,q,v}: list elt1 ...
;;; union {,q,v} {,!}: list1 ...
;;; intersection {,q,v} {,!}: list1 list2 ...
;;; list-difference {,q,v} {,!}: list1 list2 ...
;;; list-xor {,q,v} {,!}: list1 ...
;;; diff+intersection {,q,v} {,!}: list1 list2 ...

(define-interface lset-lib-interface
  (export
   ;; lset=  = list1 list2 ... -> boolean
   ;; lset<= = list1 list2 ... -> boolean
   ((lset= lset<=)
    (proc ((proc (:value :value) :boolean) :value &rest :value) :boolean))

   ;; adjoin {,q,v}: list elt1 ...
   ((adjoin adjoinq adjoinv) (proc (:value &rest :value) :value))

   ;; union {,q,v} {,!}: list1 ...
   ((union union!  unionq unionq!  unionv unionv!)
    (proc (&rest :value) :value))

   ;; intersection {,q,v} {,!}: list1 list2 ...
   ((intersection  intersection!
     intersectionq intersectionq!
     intersectionv intersectionv!) (proc (:value &rest :value) :value))

   ;; list-difference {,q,v} {,!}: list1 list2 ...
   ((list-difference  list-difference!
     list-differenceq list-differenceq!
     list-differencev list-differencev!) (proc (:value &rest :value) :value))

   ;; list-xor {,q,v} {,!}: list1 ...
   ((list-xor  list-xor!
     list-xorq list-xorq!
     list-xorv list-xorv!) (proc (&rest :value) :value))

   ;; diff+intersection {,q,v} {,!}: list1 list2 ...
   ((diff+intersection  diff+intersection!
     diff+intersectionq diff+intersectionq!
     diff+intersectionv diff+intersectionv!) (proc (:value &rest :value)
						   (some-values :value :value)))

   ;; lset-adjoin = list elt1 ...
   (lset-adjoin (proc ((proc (:value :value) :boolean) :value &rest :value) :value))

   ;; lset-union  = list1 ...	lset-xor  = list1 ...
   ;; lset-union! = list1 ...	lset-xor! = list1 ...
   ((lset-union lset-xor)
    (proc ((proc (:value :value) :boolean) &rest :value) :value))

   ;; lset-intersection  = list1 list2 ...
   ;; lset-intersection! = list1 list2 ...
   ;; lset-difference    = list1 list2 ...
   ;; lset-difference!   = list1 list2 ...
   ((lset-intersection  lset-difference
     lset-intersection! lset-difference!)
    (proc ((proc (:value :value) :boolean) :value &rest :value) :value))

   ;; lset-diff+intersection  = list1 list2 ...
   ;; lset-diff+intersection! = list1 list2 ...
   ((lset-diff+intersection lset-diff+intersection!)
    (proc ((proc (:value :value) :boolean) :value &rest :value)
	  (some-values :value :value)))
   ))
