1.0.0.22: Extensible sequences. (EXPERIMENTAL: Do Not Use As Food)
[sbcl.git] / src / pcl / sequence.lisp
diff --git a/src/pcl/sequence.lisp b/src/pcl/sequence.lisp
new file mode 100644 (file)
index 0000000..200705f
--- /dev/null
@@ -0,0 +1,900 @@
+;;;; Extensible sequences, based on the proposal by Christophe Rhodes.
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+
+;;;; This software is in the public domain and is provided with
+;;;; absolutely no warranty. See the COPYING and CREDITS files for
+;;;; more information.
+
+(in-package "SB-IMPL")
+\f
+;;;; basic protocol
+(define-condition sequence::protocol-unimplemented (type-error)
+  ())
+
+(defun sequence::protocol-unimplemented (sequence)
+  (error 'sequence::protocol-unimplemented
+         :datum sequence :expected-type '(or list vector)))
+
+(defgeneric sequence:length (sequence)
+  (:method ((s list)) (length s))
+  (:method ((s vector)) (length s))
+  (:method ((s sequence)) (sequence::protocol-unimplemented s)))
+
+(defgeneric sequence:elt (sequence index)
+  (:method ((s list) index) (elt s index))
+  (:method ((s vector) index) (elt s index))
+  (:method ((s sequence) index) (sequence::protocol-unimplemented s)))
+
+(defgeneric (setf sequence:elt) (new-value sequence index)
+  (:argument-precedence-order sequence new-value index)
+  (:method (new-value (s list) index) (setf (elt s index) new-value))
+  (:method (new-value (s vector) index) (setf (elt s index) new-value))
+  (:method (new-value (s sequence) index)
+    (sequence::protocol-unimplemented s)))
+
+(defgeneric sequence:make-sequence-like
+    (sequence length &key initial-element initial-contents)
+  (:method ((s list) length &key
+            (initial-element nil iep) (initial-contents nil icp))
+    (cond
+      ((and icp iep) (error "bar"))
+      (iep (make-list length :initial-element initial-element))
+      (icp (unless (= (length initial-contents) length)
+             (error "foo"))
+           (let ((result (make-list length)))
+             (replace result initial-contents)
+             result))
+      (t (make-list length))))
+  (:method ((s vector) length &key
+            (initial-element nil iep) (initial-contents nil icp))
+    (cond
+      ((and icp iep) (error "foo"))
+      (iep (make-array length :element-type (array-element-type s)
+                       :initial-element initial-element))
+      (icp (make-array length :element-type (array-element-type s)
+                       :initial-contents initial-contents))
+      (t (make-array length :element-type (array-element-type s)))))
+  (:method ((s sequence) length &key initial-element initial-contents)
+    (declare (ignore initial-element initial-contents))
+    (sequence::protocol-unimplemented s)))
+
+(defgeneric sequence:adjust-sequence
+    (sequence length &key initial-element initial-contents)
+  (:method ((s list) length &key initial-element (initial-contents nil icp))
+    (if (eql length 0)
+        nil
+        (let ((olength (length s)))
+          (cond
+            ((eql length olength) (if icp (replace s initial-contents) s))
+            ((< length olength)
+             (rplacd (nthcdr (1- length) s) nil)
+             (if icp (replace s initial-contents) s))
+            ((null s)
+             (let ((return (make-list length :initial-element initial-element)))
+               (if icp (replace return initial-contents) return)))
+            (t (rplacd (nthcdr (1- olength) s)
+                       (make-list (- length olength)
+                                  :initial-element initial-element))
+               (if icp (replace s initial-contents) s))))))
+  (:method ((s vector) length &rest args &key (initial-contents nil icp) initial-element)
+    (declare (ignore initial-element))
+    (cond
+      ((and (array-has-fill-pointer-p s)
+            (>= (array-total-size s) length))
+       (setf (fill-pointer s) length)
+       (if icp (replace s initial-contents) s))
+      ((eql (length s) length)
+       (if icp (replace s initial-contents) s))
+      (t (apply #'adjust-array s length args))))
+  (:method (new-value (s sequence) &rest args)
+    (declare (ignore args))
+    (sequence::protocol-unimplemented s)))
+\f
+;;;; iterator protocol
+
+;;; The general protocol
+
+(defgeneric sequence:make-sequence-iterator (sequence &key from-end start end)
+  (:method ((s sequence) &key from-end (start 0) end)
+    (multiple-value-bind (iterator limit from-end)
+        (sequence:make-simple-sequence-iterator
+         s :from-end from-end :start start :end end)
+      (values iterator limit from-end
+              #'sequence:iterator-step #'sequence:iterator-endp
+              #'sequence:iterator-element #'(setf sequence:iterator-element)
+              #'sequence:iterator-index #'sequence:iterator-copy))))
+
+;;; the simple protocol: the simple iterator returns three values,
+;;; STATE, LIMIT and FROM-END.
+
+;;; magic termination value for list :from-end t
+(defvar *exhausted* (cons nil nil))
+
+(defgeneric sequence:make-simple-sequence-iterator
+    (sequence &key from-end start end)
+  (:method ((s list) &key from-end (start 0) end)
+    (if from-end
+        (let* ((termination (if (= start 0) *exhausted* (nthcdr (1- start) s)))
+               (init (if (<= (or end (length s)) start)
+                         termination
+                         (if end (last s (- (length s) (1- end))) (last s)))))
+          (values init termination t))
+        (cond
+          ((not end) (values (nthcdr start s) nil nil))
+          (t (let ((st (nthcdr start s)))
+               (values st (nthcdr (- end start) st) nil))))))
+  (:method ((s vector) &key from-end (start 0) end)
+    (let ((end (or end (length s))))
+      (if from-end
+          (values (1- end) (1- start) t)
+          (values start end nil))))
+  (:method ((s sequence) &key from-end (start 0) end)
+    (let ((end (or end (length s))))
+      (if from-end
+          (values (1- end) (1- start) from-end)
+          (values start end nil)))))
+
+(defgeneric sequence:iterator-step (sequence iterator from-end)
+  (:method ((s list) iterator from-end)
+    (if from-end
+        (if (eq iterator s)
+            *exhausted*
+            (do* ((xs s (cdr xs)))
+                 ((eq (cdr xs) iterator) xs)))
+        (cdr iterator)))
+  (:method ((s vector) iterator from-end)
+    (if from-end
+        (1- iterator)
+        (1+ iterator)))
+  (:method ((s sequence) iterator from-end)
+    (if from-end
+        (1- iterator)
+        (1+ iterator))))
+
+(defgeneric sequence:iterator-endp (sequence iterator limit from-end)
+  (:method ((s list) iterator limit from-end)
+    (eq iterator limit))
+  (:method ((s vector) iterator limit from-end)
+    (= iterator limit))
+  (:method ((s sequence) iterator limit from-end)
+    (= iterator limit)))
+
+(defgeneric sequence:iterator-element (sequence iterator)
+  (:method ((s list) iterator)
+    (car iterator))
+  (:method ((s vector) iterator)
+    (aref s iterator))
+  (:method ((s sequence) iterator)
+    (elt s iterator)))
+
+(defgeneric (setf sequence:iterator-element) (new-value sequence iterator)
+  (:method (o (s list) iterator)
+    (setf (car iterator) o))
+  (:method (o (s vector) iterator)
+    (setf (aref s iterator) o))
+  (:method (o (s sequence) iterator)
+    (setf (elt s iterator) o)))
+
+(defgeneric sequence:iterator-index (sequence iterator)
+  (:method ((s list) iterator)
+    ;; FIXME: this sucks.  (In my defence, it is the equivalent of the
+    ;; Apple implementation in Dylan...)
+    (loop for l on s for i from 0 when (eq l iterator) return i))
+  (:method ((s vector) iterator) iterator)
+  (:method ((s sequence) iterator) iterator))
+
+(defgeneric sequence:iterator-copy (sequence iterator)
+  (:method ((s list) iterator) iterator)
+  (:method ((s vector) iterator) iterator)
+  (:method ((s sequence) iterator) iterator))
+
+(defmacro sequence:with-sequence-iterator
+    ((&rest vars) (s &rest args &key from-end start end) &body body)
+  (declare (ignore from-end start end))
+  `(multiple-value-bind (,@vars) (sequence:make-sequence-iterator ,s ,@args)
+    (declare (type function ,@(nthcdr 3 vars)))
+    ,@body))
+
+(defmacro sequence:with-sequence-iterator-functions
+    ((step endp elt setf index copy)
+     (s &rest args &key from-end start end)
+     &body body)
+  (declare (ignore from-end start end))
+  (let ((nstate (gensym "STATE")) (nlimit (gensym "LIMIT"))
+        (nfrom-end (gensym "FROM-END-")) (nstep (gensym "STEP"))
+        (nendp (gensym "ENDP")) (nelt (gensym "ELT"))
+        (nsetf (gensym "SETF")) (nindex (gensym "INDEX"))
+        (ncopy (gensym "COPY")))
+    `(sequence:with-sequence-iterator
+         (,nstate ,nlimit ,nfrom-end ,nstep ,nendp ,nelt ,nsetf ,nindex ,ncopy)
+       (,s ,@args)
+       (flet ((,step () (setq ,nstate (funcall ,nstep ,s ,nstate ,nfrom-end)))
+              (,endp () (funcall ,nendp ,s ,nstate ,nlimit ,nfrom-end))
+              (,elt () (funcall ,nelt ,s ,nstate))
+              (,setf (new-value) (funcall ,nsetf new-value ,s ,nstate))
+              (,index () (funcall ,nindex ,s ,nstate))
+              (,copy () (funcall ,ncopy ,s ,nstate)))
+         (declare (dynamic-extent #',step #',endp #',elt
+                                  #',setf #',index #',copy))
+         ,@body))))
+
+(defun sequence:canonize-test (test test-not)
+  (cond
+    (test (if (functionp test) test (fdefinition test)))
+    (test-not (if (functionp test-not)
+                  (complement test-not)
+                  (complement (fdefinition test-not))))
+    (t #'eql)))
+
+(defun sequence:canonize-key (key)
+  (or (and key (if (functionp key) key (fdefinition key))) #'identity))
+\f
+;;;; LOOP support.  (DOSEQUENCE support is present in the core SBCL
+;;;; code).
+(defun loop-elements-iteration-path (variable data-type prep-phrases)
+  (let (of-phrase)
+    (loop for (prep . rest) in prep-phrases do
+          (ecase prep
+            ((:of :in) (if of-phrase
+                           (sb-loop::loop-error "Too many prepositions")
+                           (setq of-phrase rest)))))
+    (destructuring-bind (it lim f-e step endp elt seq)
+        (loop repeat 7 collect (gensym))
+      (push `(let ((,seq ,(car of-phrase)))) sb-loop::*loop-wrappers*)
+      (push `(sequence:with-sequence-iterator (,it ,lim ,f-e ,step ,endp ,elt) (,seq))
+            sb-loop::*loop-wrappers*)
+    `(((,variable nil ,data-type)) () () nil (funcall ,endp ,seq ,it ,lim ,f-e)
+      (,variable (funcall ,elt ,seq ,it) ,it (funcall ,step ,seq ,it ,f-e))))))
+(sb-loop::add-loop-path
+ '(element elements) 'loop-elements-iteration-path sb-loop::*loop-ansi-universe*
+ :preposition-groups '((:of :in)) :inclusive-permitted nil)
+\f
+;;;; generic implementations for sequence functions.
+
+;;; FIXME: COUNT, POSITION and FIND share an awful lot of structure.
+;;; They could usefully be defined in an OAOO way.
+(defgeneric sequence:count
+    (item sequence &key from-end start end test test-not key)
+  (:argument-precedence-order sequence item))
+(defmethod sequence:count
+    (item (sequence sequence) &key from-end (start 0) end test test-not key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ((count 0))
+          ((funcall endp sequence state limit from-end) count)
+        (let ((o (funcall elt sequence state)))
+          (when (funcall test item (funcall key o))
+            (incf count))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:count-if (pred sequence &key from-end start end key)
+  (:argument-precedence-order sequence pred))
+(defmethod sequence:count-if
+    (pred (sequence sequence) &key from-end (start 0) end key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ((count 0))
+          ((funcall endp sequence state limit from-end) count)
+        (let ((o (funcall elt sequence state)))
+          (when (funcall pred (funcall key o))
+            (incf count))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:count-if-not (pred sequence &key from-end start end key)
+  (:argument-precedence-order sequence pred))
+(defmethod sequence:count-if-not
+    (pred (sequence sequence) &key from-end (start 0) end key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ((count 0))
+          ((funcall endp sequence state limit from-end) count)
+        (let ((o (funcall elt sequence state)))
+          (unless (funcall pred (funcall key o))
+            (incf count))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:find
+    (item sequence &key from-end start end test test-not key)
+  (:argument-precedence-order sequence item))
+(defmethod sequence:find
+    (item (sequence sequence) &key from-end (start 0) end test test-not key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ()
+          ((funcall endp sequence state limit from-end) nil)
+        (let ((o (funcall elt sequence state)))
+          (when (funcall test item (funcall key o))
+            (return o))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:find-if (pred sequence &key from-end start end key)
+  (:argument-precedence-order sequence pred))
+(defmethod sequence:find-if
+    (pred (sequence sequence) &key from-end (start 0) end key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ()
+          ((funcall endp sequence state limit from-end) nil)
+        (let ((o (funcall elt sequence state)))
+          (when (funcall pred (funcall key o))
+            (return o))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:find-if-not (pred sequence &key from-end start end key)
+  (:argument-precedence-order sequence pred))
+(defmethod sequence:find-if-not
+    (pred (sequence sequence) &key from-end (start 0) end key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ()
+          ((funcall endp sequence state limit from-end) nil)
+        (let ((o (funcall elt sequence state)))
+          (unless (funcall pred (funcall key o))
+            (return o))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:position
+    (item sequence &key from-end start end test test-not key)
+  (:argument-precedence-order sequence item))
+(defmethod sequence:position
+    (item (sequence sequence) &key from-end (start 0) end test test-not key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ((s (if from-end -1 1))
+           (pos (if from-end (1- (or end (length sequence))) start) (+ pos s)))
+          ((funcall endp sequence state limit from-end) nil)
+        (let ((o (funcall elt sequence state)))
+          (when (funcall test item (funcall key o))
+            (return pos))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:position-if (pred sequence &key from-end start end key)
+  (:argument-precedence-order sequence pred))
+(defmethod sequence:position-if
+    (pred (sequence sequence) &key from-end (start 0) end key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ((s (if from-end -1 1))
+           (pos (if from-end (1- (or end (length sequence))) start) (+ pos s)))
+          ((funcall endp sequence state limit from-end) nil)
+        (let ((o (funcall elt sequence state)))
+          (when (funcall pred (funcall key o))
+            (return pos))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:position-if-not
+    (pred sequence &key from-end start end key)
+  (:argument-precedence-order sequence pred))
+(defmethod sequence:position-if-not
+    (pred (sequence sequence) &key from-end (start 0) end key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :from-end from-end :start start :end end)
+      (do ((s (if from-end -1 1))
+           (pos (if from-end (1- (or end (length sequence))) start) (+ pos s)))
+          ((funcall endp sequence state limit from-end) nil)
+        (let ((o (funcall elt sequence state)))
+          (unless (funcall pred (funcall key o))
+            (return pos))
+          (setq state (funcall step sequence state from-end)))))))
+
+(defgeneric sequence:subseq (sequence start &optional end))
+(defmethod sequence:subseq ((sequence sequence) start &optional end)
+  (let* ((end (or end (length sequence)))
+         (length (- end start))
+         (result (sequence:make-sequence-like sequence length)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :start start :end end)
+      (declare (ignore limit endp))
+      (sequence:with-sequence-iterator (rstate rlimit rfrom-end rstep rendp relt rsetelt)
+          (result)
+        (declare (ignore rlimit rendp relt))
+        (do ((i 0 (+ i 1)))
+            ((>= i length) result)
+          (funcall rsetelt (funcall elt sequence state) result rstate)
+          (setq state (funcall step sequence state from-end))
+          (setq rstate (funcall rstep result rstate rfrom-end)))))))
+
+(defgeneric sequence:copy-seq (sequence))
+(defmethod sequence:copy-seq ((sequence sequence))
+  (sequence:subseq sequence 0))
+
+(defgeneric sequence:fill (sequence item &key start end))
+(defmethod sequence:fill ((sequence sequence) item &key (start 0) end)
+  (sequence:with-sequence-iterator (state limit from-end step endp elt setelt)
+      (sequence :start start :end end)
+    (declare (ignore elt))
+    (do ()
+        ((funcall endp sequence state limit from-end) sequence)
+      (funcall setelt item sequence state)
+      (setq state (funcall step sequence state from-end)))))
+
+(defgeneric sequence:nsubstitute
+    (new old sequence &key start end from-end test test-not count key)
+  (:argument-precedence-order sequence new old))
+(defmethod sequence:nsubstitute (new old (sequence sequence) &key (start 0)
+                                 end from-end test test-not count key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt setelt)
+        (sequence :start start :end end :from-end from-end)
+      (do ((c 0))
+          ((or (and count (>= c count))
+               (funcall endp sequence state limit from-end))
+           sequence)
+        (when (funcall test old (funcall key (funcall elt sequence state)))
+          (incf c)
+          (funcall setelt new sequence state))
+        (setq state (funcall step sequence state from-end))))))
+
+(defgeneric sequence:nsubstitute-if
+    (new predicate sequence &key start end from-end count key)
+  (:argument-precedence-order sequence new predicate))
+(defmethod sequence:nsubstitute-if
+    (new predicate (sequence sequence) &key (start 0) end from-end count key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt setelt)
+        (sequence :start start :end end :from-end from-end)
+      (do ((c 0))
+          ((or (and count (>= c count))
+               (funcall endp sequence state limit from-end))
+           sequence)
+        (when (funcall predicate (funcall key (funcall elt sequence state)))
+          (incf c)
+          (funcall setelt new sequence state))
+        (setq state (funcall step sequence state from-end))))))
+
+(defgeneric sequence:nsubstitute-if-not
+    (new predicate sequence &key start end from-end count key)
+  (:argument-precedence-order sequence new predicate))
+(defmethod sequence:nsubstitute-if-not
+    (new predicate (sequence sequence) &key (start 0) end from-end count key)
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt setelt)
+        (sequence :start start :end end :from-end from-end)
+      (do ((c 0))
+          ((or (and count (>= c count))
+               (funcall endp sequence state limit from-end))
+           sequence)
+        (unless (funcall predicate (funcall key (funcall elt sequence state)))
+          (incf c)
+          (funcall setelt new sequence state))
+        (setq state (funcall step sequence state from-end))))))
+
+(defgeneric sequence:substitute
+    (new old sequence &key start end from-end test test-not count key)
+  (:argument-precedence-order sequence new old))
+(defmethod sequence:substitute (new old (sequence sequence) &rest args &key
+                                (start 0) end from-end test test-not count key)
+  (declare (dynamic-extent args))
+  (declare (ignore start end from-end test test-not count key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:nsubstitute new old result args)))
+
+(defgeneric sequence:substitute-if
+    (new predicate sequence &key start end from-end count key)
+  (:argument-precedence-order sequence new predicate))
+(defmethod sequence:substitute-if (new predicate (sequence sequence) &rest args
+                                   &key (start 0) end from-end count key)
+  (declare (dynamic-extent args))
+  (declare (ignore start end from-end count key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:nsubstitute-if new predicate result args)))
+
+(defgeneric sequence:substitute-if-not
+    (new predicate sequence &key start end from-end count key)
+  (:argument-precedence-order sequence new predicate))
+(defmethod sequence:substitute-if-not
+    (new predicate (sequence sequence) &rest args &key
+     (start 0) end from-end count key)
+  (declare (dynamic-extent args))
+  (declare (ignore start end from-end count key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:nsubstitute-if-not new predicate result args)))
+
+(defun %sequence-replace (sequence1 sequence2 start1 end1 start2 end2)
+  (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1)
+      (sequence1 :start start1 :end end1)
+    (declare (ignore elt1))
+    (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+        (sequence2 :start start2 :end end2)
+      (do ()
+          ((or (funcall endp1 sequence1 state1 limit1 from-end1)
+               (funcall endp2 sequence2 state2 limit2 from-end2))
+           sequence1)
+        (funcall setelt1 (funcall elt2 sequence2 state2) sequence1 state1)
+        (setq state1 (funcall step1 sequence1 state1 from-end1))
+        (setq state2 (funcall step2 sequence2 state2 from-end2))))))
+
+(defgeneric sequence:replace
+    (sequence1 sequence2 &key start1 end1 start2 end2)
+  (:argument-precedence-order sequence2 sequence1))
+(defmethod sequence:replace
+    ((sequence1 sequence) (sequence2 sequence) &key
+     (start1 0) end1 (start2 0) end2)
+  (cond
+    ((eq sequence1 sequence2)
+     (let ((replaces (subseq sequence2 start2 end2)))
+       (%sequence-replace sequence1 replaces start1 end1 0 nil)))
+    (t (%sequence-replace sequence1 sequence2 start1 end1 start2 end2))))
+
+(defgeneric sequence:nreverse (sequence))
+(defmethod sequence:nreverse ((sequence sequence))
+  ;; FIXME: this, in particular the :from-end iterator, will suck
+  ;; mightily if the user defines a list-like structure.
+  (let ((length (length sequence)))
+    (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1)
+        (sequence :end (floor length 2))
+      (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2 setelt2)
+          (sequence :start (ceiling length 2) :from-end t)
+        (declare (ignore limit2 endp2))
+        (do ()
+            ((funcall endp1 sequence state1 limit1 from-end1) sequence)
+          (let ((x (funcall elt1 sequence state1))
+                (y (funcall elt2 sequence state2)))
+            (funcall setelt1 y sequence state1)
+            (funcall setelt2 x sequence state2))
+          (setq state1 (funcall step1 sequence state1 from-end1))
+          (setq state2 (funcall step2 sequence state2 from-end2)))))))
+
+(defgeneric sequence:reverse (sequence))
+(defmethod sequence:reverse ((sequence sequence))
+  (let ((result (copy-seq sequence)))
+    (sequence:nreverse result)))
+
+(defgeneric sequence:reduce
+    (function sequence &key from-end start end initial-value)
+  (:argument-precedence-order sequence function))
+(defmethod sequence:reduce
+    (function (sequence sequence) &key from-end (start 0) end key
+     (initial-value nil ivp))
+  (let ((key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence :start start :end end :from-end from-end)
+      (if (funcall endp sequence state limit from-end)
+          (if ivp initial-value (funcall function))
+          (do* ((state state (funcall step sequence state from-end))
+                (value (cond
+                         (ivp initial-value)
+                         (t (prog1
+                                (funcall key (funcall elt sequence state))
+                              (setq state (funcall step sequence state from-end)))))))
+               ((funcall endp sequence state limit from-end) value)
+            (let ((e (funcall key (funcall elt sequence state))))
+              (if from-end
+                  (setq value (funcall function e value))
+                  (setq value (funcall function value e)))))))))
+
+(defgeneric sequence:mismatch (sequence1 sequence2 &key from-end start1 end1
+                               start2 end2 test test-not key))
+(defmethod sequence:mismatch
+    ((sequence1 sequence) (sequence2 sequence) &key from-end (start1 0) end1
+     (start2 0) end2 test test-not key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key)))
+    (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1)
+        (sequence1 :start start1 :end end1 :from-end from-end)
+      (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+          (sequence2 :start start2 :end end2 :from-end from-end)
+        (if from-end
+            (do ((result (or end1 (length sequence1)) (1- result))
+                 (e1 (funcall endp1 sequence1 state1 limit1 from-end1)
+                     (funcall endp1 sequence1 state1 limit1 from-end1))
+                 (e2 (funcall endp2 sequence2 state2 limit2 from-end2)
+                     (funcall endp2 sequence2 state2 limit2 from-end2)))
+                ((or e1 e2) (if (and e1 e2) nil result))
+              (let ((o1 (funcall key (funcall elt1 sequence1 state1)))
+                    (o2 (funcall key (funcall elt2 sequence2 state2))))
+                (unless (funcall test o1 o2)
+                  (return result))
+                (setq state1 (funcall step1 sequence1 state1 from-end1))
+                (setq state2 (funcall step2 sequence2 state2 from-end2))))
+            (do ((result start1 (1+ result))
+                 (e1 (funcall endp1 sequence1 state1 limit1 from-end1)
+                     (funcall endp1 sequence1 state1 limit1 from-end1))
+                 (e2 (funcall endp2 sequence2 state2 limit2 from-end2)
+                     (funcall endp2 sequence2 state2 limit2 from-end2)))
+                ((or e1 e2) (if (and e1 e2) nil result))
+              (let ((o1 (funcall key (funcall elt1 sequence1 state1)))
+                    (o2 (funcall key (funcall elt2 sequence2 state2))))
+                (unless (funcall test o1 o2)
+                  (return result)))
+              (setq state1 (funcall step1 sequence1 state1 from-end1))
+              (setq state2 (funcall step2 sequence2 state2 from-end2))))))))
+
+(defgeneric sequence:search (sequence1 sequence2 &key from-end start1 end1
+                             start2 end2 test test-not key))
+(defmethod sequence:search
+    ((sequence1 sequence) (sequence2 sequence) &key from-end (start1 0) end1
+     (start2 0) end2 test test-not key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key))
+        (mainend2 (- (or end2 (length sequence2))
+                     (- (or end1 (length sequence1)) start1))))
+    (when (< mainend2 0)
+      (return-from sequence:search nil))
+    (sequence:with-sequence-iterator (statem limitm from-endm stepm endpm)
+        (sequence2 :start start2 :end mainend2 :from-end from-end)
+      (do ((s2 (if from-end mainend2 0) (if from-end (1- s2) (1+ s2))))
+          (nil)
+        (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1)
+            (sequence1 :start start1 :end end1)
+          (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+              (sequence2 :start s2)
+            (declare (ignore limit2 endp2))
+            (when (do ()
+                      ((funcall endp1 sequence1 state1 limit1 from-end1) t)
+                    (let ((o1 (funcall key (funcall elt1 sequence1 state1)))
+                          (o2 (funcall key (funcall elt2 sequence2 state2))))
+                      (unless (funcall test o1 o2)
+                        (return nil)))
+                    (setq state1 (funcall step1 sequence1 state1 from-end1))
+                    (setq state2 (funcall step2 sequence2 state2 from-end2)))
+              (return-from sequence:search s2))))
+        (when (funcall endpm sequence2 statem limitm from-endm)
+          (return nil))
+        (setq statem (funcall stepm sequence2 statem from-endm))))))
+
+(defgeneric sequence:delete
+    (item sequence &key from-end test test-not start end count key)
+  (:argument-precedence-order sequence item))
+(defmethod sequence:delete (item (sequence sequence) &key
+                            from-end test test-not (start 0) end count key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key))
+        (c 0))
+    (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1)
+        (sequence :start start :end end :from-end from-end)
+      (declare (ignore limit1 endp1 elt1))
+      (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+          (sequence :start start :end end :from-end from-end)
+        (flet ((finish ()
+                 (if from-end
+                     (replace sequence sequence
+                              :start1 start :end1 (- (length sequence) c)
+                              :start2 (+ start c) :end2 (length sequence))
+                     (unless (or (null end) (= end (length sequence)))
+                       (replace sequence sequence :start2 end :start1 (- end c)
+                                :end1 (- (length sequence) c))))
+                 (sequence:adjust-sequence sequence (- (length sequence) c))))
+          (declare (dynamic-extent #'finish))
+          (do ()
+              ((funcall endp2 sequence state2 limit2 from-end2) (finish))
+            (let ((e (funcall elt2 sequence state2)))
+              (loop
+               (when (and count (>= c count))
+                 (return))
+               (if (funcall test item (funcall key e))
+                   (progn
+                     (incf c)
+                     (setq state2 (funcall step2 sequence state2 from-end2))
+                     (when (funcall endp2 sequence state2 limit2 from-end2)
+                       (return-from sequence:delete (finish)))
+                     (setq e (funcall elt2 sequence state2)))
+                   (return)))
+              (funcall setelt1 e sequence state1))
+            (setq state1 (funcall step1 sequence state1 from-end1))
+            (setq state2 (funcall step2 sequence state2 from-end2))))))))
+
+(defgeneric sequence:delete-if
+    (predicate sequence &key from-end start end count key)
+  (:argument-precedence-order sequence predicate))
+(defmethod sequence:delete-if (predicate (sequence sequence) &key
+                               from-end (start 0) end count key)
+  (let ((key (sequence:canonize-key key))
+        (c 0))
+    (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1)
+        (sequence :start start :end end :from-end from-end)
+      (declare (ignore limit1 endp1 elt1))
+      (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+          (sequence :start start :end end :from-end from-end)
+        (flet ((finish ()
+                 (if from-end
+                     (replace sequence sequence
+                              :start1 start :end1 (- (length sequence) c)
+                              :start2 (+ start c) :end2 (length sequence))
+                     (unless (or (null end) (= end (length sequence)))
+                       (replace sequence sequence :start2 end :start1 (- end c)
+                                :end1 (- (length sequence) c))))
+                 (sequence:adjust-sequence sequence (- (length sequence) c))))
+          (declare (dynamic-extent #'finish))
+          (do ()
+              ((funcall endp2 sequence state2 limit2 from-end2) (finish))
+            (let ((e (funcall elt2 sequence state2)))
+              (loop
+               (when (and count (>= c count))
+                 (return))
+               (if (funcall predicate (funcall key e))
+                   (progn
+                     (incf c)
+                     (setq state2 (funcall step2 sequence state2 from-end2))
+                     (when (funcall endp2 sequence state2 limit2 from-end2)
+                       (return-from sequence:delete-if (finish)))
+                     (setq e (funcall elt2 sequence state2)))
+                   (return)))
+              (funcall setelt1 e sequence state1))
+            (setq state1 (funcall step1 sequence state1 from-end1))
+            (setq state2 (funcall step2 sequence state2 from-end2))))))))
+
+(defgeneric sequence:delete-if-not
+    (predicate sequence &key from-end start end count key)
+  (:argument-precedence-order sequence predicate))
+(defmethod sequence:delete-if-not (predicate (sequence sequence) &key
+                                   from-end (start 0) end count key)
+  (let ((key (sequence:canonize-key key))
+        (c 0))
+    (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1)
+        (sequence :start start :end end :from-end from-end)
+      (declare (ignore limit1 endp1 elt1))
+      (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+          (sequence :start start :end end :from-end from-end)
+        (flet ((finish ()
+                 (if from-end
+                     (replace sequence sequence
+                              :start1 start :end1 (- (length sequence) c)
+                              :start2 (+ start c) :end2 (length sequence))
+                     (unless (or (null end) (= end (length sequence)))
+                       (replace sequence sequence :start2 end :start1 (- end c)
+                                :end1 (- (length sequence) c))))
+                 (sequence:adjust-sequence sequence (- (length sequence) c))))
+          (declare (dynamic-extent #'finish))
+          (do ()
+              ((funcall endp2 sequence state2 limit2 from-end2) (finish))
+            (let ((e (funcall elt2 sequence state2)))
+              (loop
+               (when (and count (>= c count))
+                 (return))
+               (if (funcall predicate (funcall key e))
+                   (return)
+                   (progn
+                     (incf c)
+                     (setq state2 (funcall step2 sequence state2 from-end2))
+                     (when (funcall endp2 sequence state2 limit2 from-end2)
+                       (return-from sequence:delete-if-not (finish)))
+                     (setq e (funcall elt2 sequence state2)))))
+              (funcall setelt1 e sequence state1))
+            (setq state1 (funcall step1 sequence state1 from-end1))
+            (setq state2 (funcall step2 sequence state2 from-end2))))))))
+
+(defgeneric sequence:remove
+    (item sequence &key from-end test test-not start end count key)
+  (:argument-precedence-order sequence item))
+(defmethod sequence:remove (item (sequence sequence) &rest args &key
+                            from-end test test-not (start 0) end count key)
+  (declare (dynamic-extent args))
+  (declare (ignore from-end test test-not start end count key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:delete item result args)))
+
+(defgeneric sequence:remove-if
+    (predicate sequence &key from-end start end count key)
+  (:argument-precedence-order sequence predicate))
+(defmethod sequence:remove-if (predicate (sequence sequence) &rest args &key
+                               from-end (start 0) end count key)
+  (declare (dynamic-extent args))
+  (declare (ignore from-end start end count key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:delete-if predicate result args)))
+
+(defgeneric sequence:remove-if-not
+    (predicate sequence &key from-end start end count key)
+  (:argument-precedence-order sequence predicate))
+(defmethod sequence:remove-if-not (predicate (sequence sequence) &rest args
+                                   &key from-end (start 0) end count key)
+  (declare (dynamic-extent args))
+  (declare (ignore from-end start end count key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:delete-if-not predicate result args)))
+
+(defgeneric sequence:delete-duplicates
+    (sequence &key from-end test test-not start end key))
+(defmethod sequence:delete-duplicates
+    ((sequence sequence) &key from-end test test-not (start 0) end key)
+  (let ((test (sequence:canonize-test test test-not))
+        (key (sequence:canonize-key key))
+        (c 0))
+    (sequence:with-sequence-iterator (state1 limit1 from-end1 step1 endp1 elt1 setelt1)
+        (sequence :start start :end end :from-end from-end)
+      (declare (ignore limit1 endp1 elt1))
+      (sequence:with-sequence-iterator (state2 limit2 from-end2 step2 endp2 elt2)
+          (sequence :start start :end end :from-end from-end)
+        (flet ((finish ()
+                 (if from-end
+                     (replace sequence sequence
+                              :start1 start :end1 (- (length sequence) c)
+                              :start2 (+ start c) :end2 (length sequence))
+                     (unless (or (null end) (= end (length sequence)))
+                       (replace sequence sequence :start2 end :start1 (- end c)
+                                :end1 (- (length sequence) c))))
+                 (sequence:adjust-sequence sequence (- (length sequence) c))))
+          (declare (dynamic-extent #'finish))
+          (do ((end (or end (length sequence)))
+               (step 0 (1+ step)))
+              ((funcall endp2 sequence state2 limit2 from-end2) (finish))
+            (let ((e (funcall elt2 sequence state2)))
+              (loop
+               ;; FIXME: replace with POSITION once position is
+               ;; working
+               (if (> (count (funcall key e) sequence :test test :key key
+                             :start (if from-end start (+ start step 1))
+                             :end (if from-end (- end step 1) end))
+                      0)
+                   (progn
+                     (incf c)
+                     (incf step)
+                     (setq state2 (funcall step2 sequence state2 from-end2))
+                     (when (funcall endp2 sequence state2 limit2 from-end2)
+                       (return-from sequence:delete-duplicates (finish)))
+                     (setq e (funcall elt2 sequence state2)))
+                   (progn
+                     (return))))
+              (funcall setelt1 e sequence state1))
+            (setq state1 (funcall step1 sequence state1 from-end1))
+            (setq state2 (funcall step2 sequence state2 from-end2))))))))
+
+(defgeneric sequence:remove-duplicates
+    (sequence &key from-end test test-not start end key))
+(defmethod sequence:remove-duplicates
+    ((sequence sequence) &rest args &key from-end test test-not (start 0) end key)
+  (declare (dynamic-extent args))
+  (declare (ignore from-end test test-not start end key))
+  (let ((result (copy-seq sequence)))
+    (apply #'sequence:delete-duplicates result args)))
+
+(defgeneric sequence:sort (sequence predicate &key key))
+(defmethod sequence:sort ((sequence sequence) predicate &rest args &key key)
+  (declare (dynamic-extent args))
+  (declare (ignore key))
+  (let* ((length (length sequence))
+         (vector (make-array length)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence)
+      (declare (ignore limit  endp))
+      (do ((i 0 (1+ i)))
+          ((>= i length))
+        (setf (aref vector i) (funcall elt sequence state))
+        (setq state (funcall step sequence state from-end))))
+    (apply #'sort vector predicate args)
+    (sequence:with-sequence-iterator (state limit from-end step endp elt setelt)
+        (sequence)
+      (declare (ignore limit endp elt))
+      (do ((i 0 (1+ i)))
+          ((>= i length) sequence)
+        (funcall setelt (aref vector i) sequence state)
+        (setq state (funcall step sequence state from-end))))))
+
+(defgeneric sequence:stable-sort (sequence predicate &key key))
+(defmethod sequence:stable-sort
+    ((sequence sequence) predicate &rest args &key key)
+  (declare (dynamic-extent args))
+  (declare (ignore key))
+  (let* ((length (length sequence))
+         (vector (make-array length)))
+    (sequence:with-sequence-iterator (state limit from-end step endp elt)
+        (sequence)
+      (declare (ignore limit  endp))
+      (do ((i 0 (1+ i)))
+          ((>= i length))
+        (setf (aref vector i) (funcall elt sequence state))
+        (setq state (funcall step sequence state from-end))))
+    (apply #'stable-sort vector predicate args)
+    (sequence:with-sequence-iterator (state limit from-end step endp elt setelt)
+        (sequence)
+      (declare (ignore limit endp elt))
+      (do ((i 0 (1+ i)))
+          ((>= i length) sequence)
+        (funcall setelt (aref vector i) sequence state)
+        (setq state (funcall step sequence state from-end))))))