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:
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 '<<-:
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.