Next: , Previous: Examples, Up: Macros for writing loops


6.3.5 Defining sequence types

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))))