Iterate provides defmacro-clause
to make it easy to write new clauses. Here’s a simple one that builds up an FSet set:
(defmacro-clause (collecting-set x &optional into var)
`(reducing ,x by #'with into ,var initial-value (empty-set)))
But the syntax of defmacro-clause
is not as flexible as I would like. In particular, there is no way to supply more than one expression. To collect an FSet map, I would like to be able to write:
(collecting-map k v into result)
But the syntax of defmacro-clause
won’t allow that.
However, there is still hope. Iterate uses a code walker that expands macros. All we have to do to get both the benefits of defmacro-clause
(the ability to collect to a particular variable) and the syntax we want is to write two macros: a macro with the syntax that we want, which expands into an auxiliary Iterate macro.
(defmacro-clause (collecting-map-aux kv &optional into var)
`(reducing ,kv by (lambda (map kv)
(with map (car kv) (cdr kv)))
,var initial-value (empty-map)))
(defmacro collecting-map (k v &rest args)
`(collecting-map-aux (cons ,k ,v) ,@args))
And then we can write:
(iterate (for x in xs)
(collecting-map x (* x 2))