Arc Forumnew | comments | leaders | submitlogin
5 points by rntz 5063 days ago | link | parent

While the idea of "flattening out" binding forms appeals to me, since complex arc and lisp function bodies in general tend to become very nested, I don't really like the way this macro conflates flattening binding forms with automatic parenthisisation of sequential "statements". I don't see why I shouldn't just write this:

    (def shuffle-numbers (min max)
      (scope
        w/table arr @
        (for i 0 (- max min)
          (= arr.i (+i min)))
        (down i (- max min 1)
          (swap arr.i (arr (rand (+ 1 i)))))))
At the very least, I don't like the way @ "magically" differentiates between binding forms and sequential forms based on the contents of binding-function-list* . It would be better IMO to have two different special symbols - one for binding forms, one for sequential evaluation.

Although, as far as magic goes, there's a neat trick that you could do using the 'sig table, which stores signatures (that is, the parameter lists) of functions and macros. You could have 'scope or some similar macro (let's say 'magic-scope) use 'sig to look up the parameter lists of the binding macros it encounters, and use them to determine "where to put the @s". So you'd just write, for example:

    (magic-scope
      w/uniq (foo bar)
      let xyzzy (+ plugh quux)
      `(,xyzzy (,foo ,bar)))
With your macro as is, you'd have to add 'w/uniq to binding-function-list* and also insert @s, like so:

    (scope
      w/uniq (foo bar) @
      let xyzzy (+ plugh quux) @
      `(,xyzzy (,foo ,bar)))


4 points by rntz 5063 days ago | link

I've been toying with clojure recently, and there are two macros, -> and ->>, which essentially "thread" expressions through a series of forms, like so:

  (-> x (f a) (g b))
  ; macroexpands to
  (g (f x a) b)
  
  (->> x (f a) (g b))
  ; macroexpands to
  (g b (f a x))
It occurs to me that (magic-)scope is very similar to a reversed-argument form of ->>; let's call it '<<-:

  (<<-
    (w/uniq (foo bar))
    (let xyzzy (+ plugh quux))
    `(,xyzzy (,foo ,bar)))
which is equivalent to (but for this use case, more readable than):

  (->> `(xyzzy (,foo ,bar)) (let xyzzy (+ plugh quux)) (w/uniq (foo bar)))
both of which macroexpand to:

  (w/uniq (foo bar)
    (let xyzzy (+ plugh quux)
      `(,xyzzy (,foo ,bar))))
This <<- form has the advantage of not depending on any sig/binding-function-list* magic, at the expense of a few sets of parentheses. And, as I mentioned, it has a nice symmetry with ->/->>, both of which are useful macros in their own right.

-----