Arc Forumnew | comments | leaders | submitlogin
macros: w/collect and w/m-collect
5 points by almkglor 6138 days ago | 3 comments
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 ^^.


4 points by kennytilton 6138 days ago | link

Peter Norvig has the source out there somewhere for a lite CL loop if you need a starting point. Or is a better project a CL->Arc translator? :)

-----

1 point by tel 6138 days ago | link

This feels more like it's a step toward iterate instead of loop. The semantics of iterate always seem simpler, cleaner, and more lispy. It also seems like you can nearly roll your own with macros like these

   (= iterate breakable:w/m-collect:w/sum:forever:etc:etc:etc)

-----

1 point by almkglor 6138 days ago | link

I like 'loop syntax better ^^

-----