Hi all,
When writing complex functions that are supposed to work on sequences, one often laments about the lack of an iteration form that works on general sequences.
I finished my work on sequence iterators to provide several abstractions to help writing such functions. The iterators are reasonably optimized, and result in performance that should be fast enough for virtually any purpose, especially on SBCL.
The iterators are not extensible by any means, and only work on lists and vectors.
My work provides the following macros:
(with-sequence-iterator (name seq &key start end from-end) ...body...)
Binds NAME to an iterator to iterate through SEQ from START to END, possibly in reversed order if FROM-END is T.
(dosequence ((var idx) seq &key start end from-end) ...body...)
Iterates through SEQ, binding VAR to the current element, and IDX to the current index of the current element.
(dosequences (((var idx) seq &key start end from-end) &rest more) ...body...)
Iterates through several sequences simultaneously.
(dosequences* (((var idx) seq &key start end from-end) &rest more) ...body...)
Similiarly to DOSEQUENCES, but iterates through the sequences in a more sequential manner. Cf. its docstring.
(check-sequence-bounds seq start end &optional length)
Signals an error if START, END are not valid bounding indices.
(with-sequence-bounds ((seq-var seq) (start-var start) (end-var end) (length-var length)) ... body ...)
Wrapper around CHECK-SEQUENCE-BOUNDS to bind the above vars to appropriate default values, check validity of indices, and declare some types.
It can be found in my repository at
http://common-lisp.net/~trittweiler/darcs/alexandria/
As a schmankerl (tidbit), here is an implementation of a function which tests whether a given sequence is the prefix of another given sequence:
(defun begins-with-subseq (prefix sequence &key (test #'eql) (key #'identity) start1 end1 start2 end2)
"Test whether the first elements of SEQUENCE are the same as the elements of PREFIX." (dosequences* ((p prefix t :start start1 :end end1) (s sequence nil :start start2 :end end2)) (unless (funcall test (funcall key p) (funcall key s)) (return nil))))
I hope you enjoy,
-T.
"Tobias C. Rittweiler" tcr@freebits.de writes:
(dosequence ((var idx) seq &key start end from-end) ...body...)
This macro (and the DOSEQUENCES) also take an &optional result argument as third parameter.
-T.
alexandria-devel@common-lisp.net