Reputation: 105203
Instead of
(let [x 1] (my-expression))
I'm trying to use:
(let (vector x 1) (my-expression))
Don't ask why, I just like normal brackets more. But Clojure says:
let requires a vector for its binding in ...
What's wrong?
Upvotes: 3
Views: 526
Reputation: 22278
Have a look at the source for the let
macro
(defmacro let
"binding => binding-form init-expr
Evaluates the exprs in a lexical context in which the symbols in
the binding-forms are bound to their respective init-exprs or parts
therein."
{:added "1.0", :special-form true, :forms '[(let [bindings*] exprs*)]}
[bindings & body]
(assert-args let
(vector? bindings) "a vector for its binding"
(even? (count bindings)) "an even number of forms in binding vector")
`(let* ~(destructure bindings) ~@body))
You'll notice that the bindings
argument is not evaluated when the macro tries to ensure it was given correct arguments via assert-args
.
At the point when clojure evaluates (vector? bindings)
, bindings
is a form (list
) containing a fn
as the first element followed by it's arguments and therefore is not a vector
at that point.
Upvotes: 3
Reputation: 106401
let
requires a vector for it's bindings (at compile time) so trying to put a vector functional call in its place won't work (as that will only produce a vector at runtime).
However you can make your own let with a bit of macro-fu:
(defmacro mylet [bindings & exprs]
`(let ~(vec bindings) ~@exprs))
(mylet (x 1) (inc x))
=> 2
Upvotes: 3
Reputation: 200296
This code, for example, does work:
(eval `(let ~(vector 'a 1) (println ~'a)))
which means you could write your own let macro that accepts a list instead of a vector. This would be quite bad for your overall Clojure experience and I wouldn't advise it.
Upvotes: 0
Reputation: 26446
The let special form binding form is required to be a vector literal not just an expression that would evaluate to a vector.
Why? Roughly stated, the expression must be compiled before it can be evaluated. At compile-time (vector x 1)
will not have been evaluated to a vector
, it will just be a list. Indeed if it were to be evaluated, the arguments of vector
would be evaluated, meaning x
would have to be resolved. But, you don't want x
to be resolved, you want it bound.
Upvotes: 7