| Sitting bored in the office, so hacked together some code. Untested ^^ ; This is simple, returns just one list
(mac w/collect body
" Creates a `collect' function callable within `body',
which collects arguments passed to it into a list in a `collected' variable.
Returns the collected list.
The values are collected in the correct order.
See also [[accum]] "
(w/uniq tl
`(let (collected collect ,tl) nil
(= collect
(fn (c)
(if collected
(do (= (cdr ,tl) (cons c nil))
(= ,tl (cdr ,tl)))
(do (= collected (cons c nil))
(= ,tl collected)))))
,@body
collected)))
; more complex: use a "mnemonic" collect!var
; and collected!var.
(mac w/m-collect body
(w/uniq tl
`(let (collected collect ,tl) nil
(= collected (table) ,tl (table))
(= collect
(fn (s . args)
(let f (fn (c)
(if (collected s)
(do
(= (cdr (,tl s)) (cons c nil))
(= (, tl s) (cdr (,tl s))))
(do
(= (collected s) (cons c nil))
(= (,tl s) (collected s)))))
; implicitly curry, so the user can use
; collect!foo.x or (collect!foo x)
(if args (apply f args)
f))))
; user has responsibility for returning the lists
; in the order he or she wants.
,@body)))
; sample
(= s "hello world")
(breakable:w/m-collect:each c s
(if
(~alphadig c)
(break (list collected!vowels collected!consonants))
(in (downcase c) #\a #\e #\i #\o #\u)
(collect!vowels c)
; else
(collect!consonants c)))
That said, maybe we should implement cl-loop ^^. |