## Creating a New SRFI-42 Generator

You have a new datatype, in this example a `matrix`

, and you want users to be able to iterate over it using SRFI-42.

You should define your own **typed generator**, just like `:vector`

, `:list`

, etc. Assume that the functions `matrix-rows`

, `matrix-cols`

, and `matrix-ref`

are defined for getting the dimensions and elements of a matrix. You should define a new syntax transformer which expands into an instance of `:do`

(or any other generator, if your needs are simple):

(define-syntax :matrix
(syntax-rules (index)
((:matrix cc x (index i j) mexpr)
(:do cc
(let ((m mexpr)
(rows #f)
(cols #f))
(set! rows (matrix-rows m))
(set! cols (matrix-cols m)))
((i 0) (j 0))
(< i rows)
(let ((x (matrix-ref m i j))
(i+1 (+ i 1))
(j+1 (+ j 1))
(wrap? #f))
(set! wrap? (>= j+1 cols)))
#t
((if wrap? i+1 i)
(if wrap? 0 j+1))))
((:matrix cc x mexpr)
(:matrix cc x (index i j) mexpr))))

The macros in SRFI-42 are all written using CPS; the `cc`

argument contains the "continuation" form which will continue the expansion of the loop after this generator has been handled.

The `:do`

generator expands into

(:do (let (<ob>*) <oc>*) (<lb>*) <ne1?> (let (<ib>*) <ic>*) <ne2?> (<ls>*))
=>
(let (<ob>*)
<oc>*
(let loop (<lb>*)
(if <ne1?>
(let (<ib>*)
<ic>*
payload
(if <ne2?>
(loop <ls>*) )))))

allowing us to write "named-let" loops with our macro. (Note that we have to pass the `cc`

argument to `:do`

inside our macro, even though it doesn't appear in the expansion above.)

So, the `:matrix`

generator expands into

(:matrix x (index i j) M)
=>
(let ((m matrix)
(rows #f)
(cols #f))
(set! rows (matrix-rows m))
(set! cols (matrix-cols m))
(let loop ((i 0) (j 0))
(if (< i rows)
(let ((x (matrix-ref m i j))
(i+1 (+ i 1))
(j+1 (+ j 1))
(wrap? #f))
(set! wrap? (>= j+1 cols))
(if #t
(begin
(do-payload ...)
(loop (if wrap? i+1 i)
(if wrap? 0 j+1))))))))

which is exactly the "named-let" loop we would have written to iterate over the elements of `matrix`

in row-major order.

Note that we supply both an `(index i j)`

and non-indexed generator form, where `index`

is a `syntax-rules`

literal.

-- WillFarr - 24 Aug 2007