From 1ccf8f6d96c761ea4d50f8194fc6ed6910a2ba9c Mon Sep 17 00:00:00 2001 From: Jan Moringen Date: Fri, 3 May 2013 01:37:01 +0200 Subject: [PATCH] Add extensible generic sequences to manual * Some generic functions in the SEQUENCE package needed documentation. * Added a node "Extensible Sequences" in doc/manual/beyond-ansi.texinfo. * Mention "Extensible Sequences" in doc/manual/intro.texinfo". fixes lp#994528 --- NEWS | 2 + doc/manual/Makefile | 4 +- doc/manual/beyond-ansi.texinfo | 219 ++++++++++++++++++++++++++++++++++++---- doc/manual/intro.texinfo | 62 ++++++------ src/code/seq.lisp | 15 +-- src/pcl/sequence.lisp | 155 +++++++++++++++++++++++----- 6 files changed, 379 insertions(+), 78 deletions(-) diff --git a/NEWS b/NEWS index 11a6507..ceb23aa 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ changes relative to sbcl-1.1.7: * notice: The implementation of MAP-ALLOCATED-OBJECTS (the heart of ROOM, plus a few SB-INTROSPECT functions) has been completely rewritten; it may now exhibit different bugs than before. + * enhancement: add section about extensible sequence to manual + (lp#994528) * enhancement: RUN-PROGRAM supports a :DIRECTORY argument to set the working directory of the spawned process. (lp#791800) (patch by Matthias Benkard) diff --git a/doc/manual/Makefile b/doc/manual/Makefile index 2f15a72..e82c172 100644 --- a/doc/manual/Makefile +++ b/doc/manual/Makefile @@ -19,7 +19,7 @@ MODULES=':sb-md5 :sb-queue :sb-concurrency :sb-rotate-byte :sb-grovel \ :sb-sprof :sb-bsd-sockets :sb-cover :sb-posix' # List of package names that docstring docs will be created for. PACKAGES=":COMMON-LISP :SB-ALIEN :SB-DEBUG :SB-EXT :SB-GRAY :SB-MOP \ - :SB-PCL :SB-SYS \ + :SB-PCL :SB-SYS :SB-SEQUENCE \ :SB-PROFILE :SB-THREAD :SB-MD5 :SB-QUEUE :SB-ROTATE-BYTE \ :SB-SPROF :SB-BSD-SOCKETS :SB-COVER :SB-POSIX :SB-CONCURRENCY" @@ -110,7 +110,7 @@ tempfiles-stamp: touch tempfiles-stamp .PHONY: clean -clean: +clean: rm -f *~ *.bak *.orig \#*\# .\#* texput.log *.fasl rm -rf $(HTMLDIRS) $(DOCSTRINGDIR) rm -f $(HTMLFILES) diff --git a/doc/manual/beyond-ansi.texinfo b/doc/manual/beyond-ansi.texinfo index 39f871f..d010cf0 100644 --- a/doc/manual/beyond-ansi.texinfo +++ b/doc/manual/beyond-ansi.texinfo @@ -7,20 +7,21 @@ ANSI standard. SBCL doesn't support as many extensions as CMUCL, but it still has quite a few. @xref{Contributed Modules}. @menu -* Reader Extensions:: -* Package-Local Nicknames:: -* Package Variance:: -* Garbage Collection:: -* Metaobject Protocol:: -* Support For Unix:: -* Customization Hooks for Users:: -* Tools To Help Developers:: -* Resolution of Name Conflicts:: -* Hash Table Extensions:: -* Random Number Generation:: -* Miscellaneous Extensions:: -* Stale Extensions:: -* Efficiency Hacks:: +* Reader Extensions:: +* Package-Local Nicknames:: +* Package Variance:: +* Garbage Collection:: +* Metaobject Protocol:: +* Extensible Sequences:: +* Support For Unix:: +* Customization Hooks for Users:: +* Tools To Help Developers:: +* Resolution of Name Conflicts:: +* Hash Table Extensions:: +* Random Number Generation:: +* Miscellaneous Extensions:: +* Stale Extensions:: +* Efficiency Hacks:: @end menu @node Reader Extensions @@ -362,14 +363,198 @@ to the constant @code{+slot-unbound+}. @end itemize +@node Extensible Sequences +@comment node-name, next, previous, up +@section Extensible Sequences + +@menu +* Iterator Protocol:: +* Simple Iterator Protocol:: +@end menu + +ANSI Common Lisp has a class @cl{sequence} with subclasses @cl{list} and +@cl{vector} on which the ``sequence functions'' like @cl{find}, +@cl{subseq}, etc. operate. As an extension to the ANSI specification, +SBCL allows additional subclasses of @cl{sequence} to be defined +@footnote{A motivation, rationale and additional examples for the design +of this extension can be found in the paper @cite{Rhodes, Christophe +(2007): User-extensible sequences in Common Lisp} available for download +at +@url{http://doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf}.}. + +Users of this extension just make instances of @cl{sequence} subclasses +and transparently operate on them using sequence functions: +@lisp +(coerce (subseq (make-instance 'my-sequence) 5 10) 'list) +@end lisp +From this perspective, no distinction between builtin and user-defined +@cl{sequence} subclasses should be necessary. + +Providers of the extension, that is user-defined @cl{sequence} +subclasses, have to adhere to a ``sequence protocol'' which consists of +a set of generic functions in the @code{sequence} package. +@c +A minimal @cl{sequence} subclass has to specify @cl{standard-object} and +@cl{sequence} as its superclasses and has to be the specializer of the +@code{sequence} parameter of methods on at least the following generic +functions: + +@include fun-sb-sequence-length.texinfo +@include fun-sb-sequence-elt.texinfo +@include fun-sb-sequence-setf-elt.texinfo +@include fun-sb-sequence-adjust-sequence.texinfo +@include fun-sb-sequence-make-sequence-like.texinfo + +@sequence{make-sequence-like} is needed for functions returning +freshly-allocated sequences such as @cl{subseq} or +@cl{copy-seq}. @sequence{adjust-sequence} is needed for functions which +destructively modify their arguments such as @cl{delete}. In fact, all +other sequence functions can be implemented in terms of the above +functions and actually are, if no additional methods are +defined. However, relying on these generic implementations, in +particular not implementing the iterator protocol can incur a high +performance penalty @xref{Iterator Protocol}. + +In addition to the mandatory functions above, methods on the following +sequence functions can be defined: + +@include fun-sb-sequence-emptyp.texinfo + +@itemize +@item +@sequence{count}, @sequence{count-if}, @sequence{count-if-not} + +@item +@sequence{find}, @sequence{find-if}, @sequence{find-if-not} + +@item +@sequence{position}, @sequence{position-if}, @sequence{position-if-not} + +@item +@sequence{subseq} + +@item +@sequence{copy-seq} + +@item +@sequence{fill} + +@item +@sequence{nsubstitue}, @sequence{nsubstitue-if}, +@sequence{nsubstitue-if-not}, @sequence{substitue}, +@sequence{substitue-if}, @sequence{substitue-if-not} + +@item +@sequence{replace} + +@item +@sequence{nreverse}, @sequence{reverse} + +@item +@sequence{reduce} + +@item +@sequence{mismatch} + +@item +@sequence{search} + +@item +@sequence{delete}, @sequence{delete-if}, @sequence{delete-if-not}, +@sequence{remove}, @sequence{remove-if}, @sequence{remove-if-not}, + +@item +@sequence{delete-duplicates}, @sequence{remove-duplicates} + +@item +@sequence{sort}, @sequence{stable-sort} +@end itemize + +In the spirit of @cl{dolist}, generic sequences can be traversed using +the macro + +@include macro-sb-sequence-dosequence.texinfo + +@node Iterator Protocol +@comment node-name, next, previous, up +@subsection Iterator Protocol + +The iterator protocol allows subsequently accessing some or all elements +of a sequence in forward or reverse direction. Users first call +@sequence{make-sequence-iterator} to create an iteration state and +receive functions to query and mutate it. These functions allow, among +other things, moving to, retrieving or modifying elements of the +sequence. An iteration state consists of a state object, a limit object, +a from-end indicator and the following six functions to query or mutate +this state: +@deffn {Function} @code{step function} sequence iterator from-end +Moves the iterator one position forward or backward in the associated +sequence depending on the iteration direction. +@end deffn +@deffn {Function} @code{endp function} sequence iterator limit from-end +Returns non-@code{nil} when the iterator has reached the end of the +associated sequence with respect to the iteration direction. +@end deffn +@deffn {Function} @code{element function} sequence iterator +Returns the sequence element associated to the current position of the +iteration. +@end deffn +@deffn {Function} @code{setf element function} new-value sequence iterator +Destructively modifies the associates sequence by replacing the sequence +element associated to the current iteration position with a new value. +@end deffn +@deffn {Function} @code{index function} sequence iterator +Returns the position of the iteration in the associated sequence. +@end deffn +@deffn {Function} @code{copy function} sequence iterator +Returns a copy of the iteration state which can be mutated independently +of the copied iteration state. +@end deffn + +An iterator is created by calling: + +@include fun-sb-sequence-make-sequence-iterator.texinfo + +Note that @sequence{make-sequence-iterator} calls +@sequence{make-simple-sequence-iterator} when there is no specialized +method for a particular @cl{sequence} subclass. @xref{Simple Iterator +Protocol}. + +The following convenience macros simplify traversing sequences using +iterators: + +@include macro-sb-sequence-with-sequence-iterator.texinfo +@include macro-sb-sequence-with-sequence-iterator-functions.texinfo + +@node Simple Iterator Protocol +@comment node-name, next, previous, up +@subsection Simple Iterator Protocol + +For cases in which the full flexibility and performance of the general +sequence iterator protocol is not required, there is a simplified +sequence iterator protocol consisting of a few generic functions which +can be specialized for iterator classes: + +@include fun-sb-sequence-iterator-step.texinfo +@include fun-sb-sequence-iterator-endp.texinfo +@include fun-sb-sequence-iterator-element.texinfo +@include fun-sb-sequence-setf-iterator-element.texinfo +@include fun-sb-sequence-iterator-index.texinfo +@include fun-sb-sequence-iterator-copy.texinfo + +Iterator objects implementing the above simple iteration protocol are +created by calling the following generic function: + +@include fun-sb-sequence-make-simple-sequence-iterator.texinfo + @node Support For Unix @comment node-name, next, previous, up @section Support For Unix @menu -* Command-line arguments:: -* Querying the process environment:: -* Running external programs:: +* Command-line arguments:: +* Querying the process environment:: +* Running external programs:: @end menu @node Command-line arguments diff --git a/doc/manual/intro.texinfo b/doc/manual/intro.texinfo index a9f2eb1..ddeeeaa 100644 --- a/doc/manual/intro.texinfo +++ b/doc/manual/intro.texinfo @@ -8,13 +8,13 @@ not on behavior which is common to all implementations of ANSI Common Lisp. @menu -* ANSI Conformance:: -* Extensions:: -* Idiosyncrasies:: -* Development Tools:: -* More SBCL Information:: -* More Common Lisp Information:: -* History and Implementation of SBCL:: +* ANSI Conformance:: +* Extensions:: +* Idiosyncrasies:: +* Development Tools:: +* More SBCL Information:: +* More Common Lisp Information:: +* History and Implementation of SBCL:: @end menu @@ -65,6 +65,10 @@ non-blocking IO on multiple streams without using threads. @code{sb-mop} package provides a metaobject protocol for the Common Lisp Object System as described in @cite{Art of Metaobject Protocol}. +@item Extensible Sequences +SBCL allows users to define subclasses of the @code{sequence} +class. @xref{Extensible Sequences}. + @item Native Threads SBCL has native threads on x86/Linux, capable of taking advantage of SMP on multiprocessor machines. @xref{Threading}. @@ -149,11 +153,11 @@ deals with choices that the ANSI standard leaves to the implementation. @menu -* Declarations:: -* FASL Format:: -* Compiler-only Implementation:: -* Defining Constants:: -* Style Warnings:: +* Declarations:: +* FASL Format:: +* Compiler-only Implementation:: +* Defining Constants:: +* Style Warnings:: @end menu @node Declarations @@ -227,7 +231,7 @@ compiling and loading reasonable code like runs into this undefined behavior. Many implementations of Common Lisp try to help the programmer around this annoyance by silently accepting the undefined code and trying to do what the programmer probably -meant. +meant. SBCL instead treats the undefined behavior as an error. Often such code can be rewritten in portable ANSI Common Lisp which has the @@ -254,13 +258,13 @@ SBCL gives style warnings about various kinds of perfectly legal code, e.g. @itemize - + @item @code{defmethod} without a preceding @code{defgeneric}; - + @item multiple @code{defun}s of the same symbol in different units; - + @item special variables not named in the conventional @code{*foo*} style, and lexical variables unconventionally named in the @code{*foo*} style @@ -288,9 +292,9 @@ case, but still isn't as of SBCL 0.7.6.) @section Development Tools @menu -* Editor Integration:: -* Language Reference:: -* Generating Executables:: +* Editor Integration:: +* Language Reference:: +* Generating Executables:: @end menu @node Editor Integration @@ -307,7 +311,7 @@ Currently @dfn{SLIME}@footnote{Historically, the ILISP package at @uref{http://ilisp.cons.org/} provided similar functionality, but it does not support modern SBCL versions.} (Superior Lisp Interaction Mode for Emacs) together with Emacs is recommended for use with -SBCL, though other options exist as well. +SBCL, though other options exist as well. SLIME can be downloaded from @uref{http://www.common-lisp.net/project/slime/}. @@ -339,10 +343,10 @@ sb-ext:save-lisp-and-die}. @section More SBCL Information @menu -* SBCL Homepage:: -* Online Documentation:: -* Additional Documentation Files:: -* Internals Documentation:: +* SBCL Homepage:: +* Online Documentation:: +* Additional Documentation Files:: +* Internals Documentation:: @end menu @node SBCL Homepage @@ -417,9 +421,9 @@ it is not installed by default. @section More Common Lisp Information @menu -* Internet Community:: -* Third-party Libraries:: -* Common Lisp Books:: +* Internet Community:: +* Third-party Libraries:: +* Common Lisp Books:: @end menu @node Internet Community @@ -462,7 +466,7 @@ learn about Common Lisp, some books stand out: @item Practical Common Lisp, by Peter Seibel An excellent introduction to the language, covering both the basics and ``advanced topics'' like macros, CLOS, and packages. Available -both in print format and on the web: @uref{http://www.gigamonkeys.com/book/}. +both in print format and on the web: @uref{http://www.gigamonkeys.com/book/}. @item Paradigms Of Artificial Intelligence Programming, by Peter Norvig Good information on general Common Lisp programming, and many @@ -556,7 +560,7 @@ the @code{eval} function only truly ``interprets'' a few easy kinds of forms, such as symbols which are @code{boundp}. More complicated forms are evaluated by calling @code{compile} and then calling @code{funcall} on the returned result. - + The direct ancestor of SBCL is the x86 port of CMUCL. This port was in some ways the most cobbled-together of all the CMUCL ports, since a number of strange changes had to be made to support the register-poor diff --git a/src/code/seq.lisp b/src/code/seq.lisp index 2cd9d52..54c7c02 100644 --- a/src/code/seq.lisp +++ b/src/code/seq.lisp @@ -798,24 +798,27 @@ many elements are copied." ;;;; CONCATENATE -(defmacro sb!sequence:dosequence ((e sequence &optional return) &body body) +(defmacro sb!sequence:dosequence ((element sequence &optional return) &body body) + #!+sb-doc + "Executes BODY with ELEMENT subsequently bound to each element of + SEQUENCE, then returns RETURN." (multiple-value-bind (forms decls) (parse-body body :doc-string-allowed nil) (let ((s sequence) (sequence (gensym "SEQUENCE"))) `(block nil (let ((,sequence ,s)) (seq-dispatch ,sequence - (dolist (,e ,sequence ,return) ,@body) - (do-vector-data (,e ,sequence ,return) ,@body) + (dolist (,element ,sequence ,return) ,@body) + (do-vector-data (,element ,sequence ,return) ,@body) (multiple-value-bind (state limit from-end step endp elt) (sb!sequence:make-sequence-iterator ,sequence) (do ((state state (funcall step ,sequence state from-end))) ((funcall endp ,sequence state limit from-end) - (let ((,e nil)) + (let ((,element nil)) ,@(filter-dolist-declarations decls) - ,e + ,element ,return)) - (let ((,e (funcall elt ,sequence state))) + (let ((,element (funcall elt ,sequence state))) ,@decls (tagbody ,@forms)))))))))) diff --git a/src/pcl/sequence.lisp b/src/pcl/sequence.lisp index 89912ad..386c64c 100644 --- a/src/pcl/sequence.lisp +++ b/src/pcl/sequence.lisp @@ -20,24 +20,46 @@ (defgeneric sequence:emptyp (sequence) (:method ((s list)) (null s)) (:method ((s vector)) (zerop (length s))) - (:method ((s sequence)) (zerop (length s)))) + (:method ((s sequence)) (zerop (length s))) + ;; TODO question for reviewer: Is this correct? Sometimes, #!+sb-doc + ;; (with "!") is used (applies to following docstring as well). + #+sb-doc + (:documentation + "Returns T if SEQUENCE is an empty sequence and NIL + otherwise. Signals an error if SEQUENCE is not a sequence.")) (defgeneric sequence:length (sequence) (:method ((s list)) (length s)) (:method ((s vector)) (length s)) - (:method ((s sequence)) (sequence::protocol-unimplemented s))) + (:method ((s sequence)) (sequence::protocol-unimplemented s)) + #+sb-doc + (:documentation + "Returns the length of SEQUENCE or signals a PROTOCOL-UNIMPLEMENTED + error if the sequence protocol is not implemented for the class of + SEQUENCE.")) (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))) + (:method ((s sequence) index) (sequence::protocol-unimplemented s)) + #+sb-doc + (:documentation + "Returns the element at position INDEX of SEQUENCE or signals a + PROTOCOL-UNIMPLEMENTED error if the sequence protocol is not + implemented for the class of SEQUENCE.")) (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))) + (sequence::protocol-unimplemented s)) + #+sb-doc + (:documentation + "Replaces the element at position INDEX of SEQUENCE with NEW-VALUE + and returns NEW-VALUE or signals a PROTOCOL-UNIMPLEMENTED error if + the sequence protocol is not implemented for the class of + SEQUENCE.")) (defgeneric sequence:make-sequence-like (sequence length &key initial-element initial-contents) @@ -63,7 +85,16 @@ (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))) + (sequence::protocol-unimplemented s)) + #+sb-doc + (:documentation + "Returns a freshly allocated sequence of length LENGTH and of the + same class as SEQUENCE. Elements of the new sequence are + initialized to INITIAL-ELEMENT, if supplied, initialized to + INITIAL-CONTENTS if supplied, or identical to the elements of + SEQUENCE if neither is supplied. Signals a PROTOCOL-UNIMPLEMENTED + error if the sequence protocol is not implemented for the class of + SEQUENCE.")) (defgeneric sequence:adjust-sequence (sequence length &key initial-element initial-contents) @@ -95,7 +126,17 @@ (t (apply #'adjust-array s length args)))) (:method (new-value (s sequence) &rest args) (declare (ignore args)) - (sequence::protocol-unimplemented s))) + (sequence::protocol-unimplemented s)) + #+sb-doc + (:documentation + "Return destructively modified SEQUENCE or a freshly allocated + sequence of the same class as SEQUENCE of length LENGTH. Elements + of the returned sequence are initialized to INITIAL-ELEMENT, if + supplied, initialized to INITIAL-CONTENTS if supplied, or identical + to the elements of SEQUENCE if neither is supplied. Signals a + PROTOCOL-UNIMPLEMENTED error if the sequence protocol is not + implemented for the class of SEQUENCE.")) + ;;;; iterator protocol @@ -114,7 +155,26 @@ (declare (ignore from-end start end)) (error 'type-error :datum s - :expected-type 'sequence))) + :expected-type 'sequence)) + #+sb-doc + (:documentation + "Returns a sequence iterator for SEQUENCE or, if START and/or END + are supplied, the subsequence bounded by START and END as nine + values: + + 1. iterator state + 2. limit + 3. from-end + 4. step function + 5. endp function + 6. element function + 7. setf element function + 8. index function + 9. copy state function + + If FROM-END is NIL, the constructed iterator visits the specified + elements in the order in which they appear in SEQUENCE. Otherwise, + the elements are visited in the opposite order.")) ;;; the simple protocol: the simple iterator returns three values, ;;; STATE, LIMIT and FROM-END. @@ -144,7 +204,19 @@ (let ((end (or end (length s)))) (if from-end (values (1- end) (1- start) from-end) - (values start end nil))))) + (values start end nil)))) + #+sb-doc + (:documentation + "Returns a sequence iterator for SEQUENCE, START, END and FROM-END + as three values: + + 1. iterator state + 2. limit + 3. from-end + + The returned iterator can be used with the generic iterator + functions ITERATOR-STEP, ITERATOR-ENDP, ITERATOR-ELEMENT, (SETF + ITERATOR-ELEMENT), ITERATOR-INDEX and ITERATOR-COPY.")) (defgeneric sequence:iterator-step (sequence iterator from-end) (:method ((s list) iterator from-end) @@ -161,7 +233,11 @@ (:method ((s sequence) iterator from-end) (if from-end (1- iterator) - (1+ iterator)))) + (1+ iterator))) + #+sb-doc + (:documentation + "Moves ITERATOR one position forward or backward in SEQUENCE + depending on the iteration direction encoded in FROM-END.")) (defgeneric sequence:iterator-endp (sequence iterator limit from-end) (:method ((s list) iterator limit from-end) @@ -169,7 +245,12 @@ (:method ((s vector) iterator limit from-end) (= iterator limit)) (:method ((s sequence) iterator limit from-end) - (= iterator limit))) + (= iterator limit)) + #+sb-doc + (:documentation + "Returns non-NIL when ITERATOR has reached LIMIT (which may + correspond to the end of SEQUENCE) with respect to the iteration + direction encoded in FROM-END.")) (defgeneric sequence:iterator-element (sequence iterator) (:method ((s list) iterator) @@ -177,7 +258,11 @@ (:method ((s vector) iterator) (aref s iterator)) (:method ((s sequence) iterator) - (elt s iterator))) + (elt s iterator)) + #+sb-doc + (:documentation + "Returns the element of SEQUENCE associated to the position of + ITERATOR.")) (defgeneric (setf sequence:iterator-element) (new-value sequence iterator) (:method (o (s list) iterator) @@ -185,7 +270,11 @@ (:method (o (s vector) iterator) (setf (aref s iterator) o)) (:method (o (s sequence) iterator) - (setf (elt s iterator) o))) + (setf (elt s iterator) o)) + #+sb-doc + (:documentation + "Destructively modifies SEQUENCE by replacing the sequence element + associated to position of ITERATOR with NEW-VALUE.")) (defgeneric sequence:iterator-index (sequence iterator) (:method ((s list) iterator) @@ -193,15 +282,27 @@ ;; 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)) + (:method ((s sequence) iterator) iterator) + #+sb-doc + (:documentation + "Returns the position of ITERATOR in SEQUENCE.")) (defgeneric sequence:iterator-copy (sequence iterator) (:method ((s list) iterator) iterator) (:method ((s vector) iterator) iterator) - (:method ((s sequence) iterator) iterator)) + (:method ((s sequence) iterator) iterator) + #+sb-doc + (:documentation + "Returns a copy of ITERATOR which also traverses SEQUENCE but can + be mutated independently of ITERATOR.")) (defmacro sequence:with-sequence-iterator - ((&rest vars) (s &rest args &key from-end start end) &body body) + ((&rest vars) (sequence &rest args &key from-end start end) &body body) + #+sb-doc + "Executes BODY with the elements of VARS bound to the iteration + state returned by MAKE-SEQUENCE-ITERATOR for SEQUENCE and + ARGS. Elements of VARS may be NIL in which case the corresponding + value returned by MAKE-SEQUENCE-ITERATOR is ignored." (declare (ignore from-end start end)) (let* ((ignored '()) (vars (mapcar (lambda (x) @@ -209,15 +310,21 @@ (push name ignored) name))) vars))) - `(multiple-value-bind (,@vars) (sequence:make-sequence-iterator ,s ,@args) + `(multiple-value-bind (,@vars) (sequence:make-sequence-iterator ,sequence ,@args) (declare (type function ,@(nthcdr 3 vars)) (ignore ,@ignored)) ,@body))) (defmacro sequence:with-sequence-iterator-functions ((step endp elt setf index copy) - (s &rest args &key from-end start end) + (sequence &rest args &key from-end start end) &body body) + #+sb-doc + "Executes BODY with the names STEP, ENDP, ELT, SETF, INDEX and COPY + bound to local functions which execute the iteration state query and + mutation functions returned by MAKE-SEQUENCE-ITERATOR for SEQUENCE + and ARGS. STEP, ENDP, ELT, SETF, INDEX and COPY have dynamic + extent." (declare (ignore from-end start end)) (let ((nstate (gensym "STATE")) (nlimit (gensym "LIMIT")) (nfrom-end (gensym "FROM-END-")) (nstep (gensym "STEP")) @@ -226,13 +333,13 @@ (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))) + (,sequence,@args) + (flet ((,step () (setq ,nstate (funcall ,nstep ,sequence,nstate ,nfrom-end))) + (,endp () (funcall ,nendp ,sequence,nstate ,nlimit ,nfrom-end)) + (,elt () (funcall ,nelt ,sequence,nstate)) + (,setf (new-value) (funcall ,nsetf new-value ,sequence,nstate)) + (,index () (funcall ,nindex ,sequence,nstate)) + (,copy () (funcall ,ncopy ,sequence,nstate))) (declare (truly-dynamic-extent #',step #',endp #',elt #',setf #',index #',copy)) ,@body)))) -- 1.7.10.4