|
|
|
|
|
by gruseom
4911 days ago
|
|
abusing binding vectors to add in extra stuff that doesn't, in itself, have anything to do with binding names to values I'm not familiar with the Clojure examples you mention, but it's interesting that Common Lisp provides directives like &rest for similar purposes. |
|
Here's a Clojure example:
user=> (for [x [0 1 2 3 4 5] :let [y (* x 3)] :when (even? y) z [1 2] [y z]) ([0 1] [0 2] [6 1] [6 2] [12 1] [12 2])
The binding vector for 'for' takes alternating name/value pairs, except it also allows these special keywords whose semantics affect the environment of the subsequent bindings, and whether the bindings are even evaluated, as well as the environment of the body expression (and whether it's evaluated). This strikes me as kind of ugly. The same can be done like this, using that mdo macro:
with identical results, or, as above, like this: Of course, if you think of a macro like "for" of consisting of a binding vector followed by an expression (or a sequence wrapped in an explicit do), there's no other place for the whens and lets that you want to use to control evaluation of (the environments of) the various bindings than the binding vector itself.If I'm not mistaken, Common Lisp's loop macro (e.g.) isn't like this---that is, it establishes its own little mini language, instead of mimicking forms found elsewhere in the language (the way Clojure's for loop control constructs are all stuffed into a "binding vector" similar to what might be found in a defn). Now it's true that something like "let y = (* x 3)" is not very Lispy at all. But neither, I think, is having something like ":when (even? y)", a sequence of two elements in a flat vector, actually govern bindings and execution of things that follow it but which it doesn't enclose.