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