[alexandria-devel] Sequence Iterators.

Tobias C. Rittweiler tcr at freebits.de
Sat Jul 12 17:06:56 UTC 2008


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.




More information about the alexandria-devel mailing list