Next: Loop macro expansion, Previous: Examples, Up: Macros for writing loops
The sequence types are object-oriented macros similar to enumerations.
An asynchronous sequence macro needs to supply three values: #f
to indicate that it is not synchronous, a list of state variables and
their initializers, and the code for one iteration. The first two
methods are written in continuation-passing style: they take another
macro and argument to which to pass their result. See [Friedman 00]
for more details on the theory behind how CPS macros work. The
sync
method receives no extra arguments. The state-vars
method is passed a list of names that will be bound to the arguments of
the sequence. The final method, for stepping the sequence forward, is
passed the list of names bound to the arguments and the list of state
variables. In addition, there is a variable to be bound to the next
element of the sequence, the body expression for the loop, and an
expression for terminating the loop.
As an example, the definition of list*
is:
(define-syntax list* (syntax-rules (SYNC STATE-VARS STEP) ((LIST* SYNC (next more)) (next #F more)) ((LIST* STATE-VARS (start-list) (next more)) (next ((list-var start-list)) more)) ((LIST* STEP (start-list) (list-var) value-var loop-body tail-exp) (IF (NULL? list-var) tail-exp (LET ((value-var (CAR list-var)) (list-var (CDR list-var))) loop-body)))))
Synchronized sequences are similar, except that they need to provide a termination test to be used when some other synchronized method terminates the loop. To continue the example:
(define-syntax list% (syntax-rules (SYNC DONE) ((LIST% SYNC (next more)) (next #T more)) ((LIST% DONE (start-list) (list-var)) (NULL? list-var)) ((LIST% . anything-else) (LIST* . anything-else))))