Why doesn't LET work with VECTOR?
Instead
(let [x 1] (my-expression))
I am trying to use:
(let (vector x 1) (my-expression))
Don't ask why, I like the regular parentheses better. But Clojure says:
let requires a vector for its binding in ...
What's wrong?
The let special form The required form must be a vector literal, not just an expression that evaluates to a vector.
Why? Roughly speaking, an expression must be compiled before it can be evaluated. At compile time , it will (vector x 1)
not evaluate to before vector
, it will just be a list. Indeed, if it were evaluated, the arguments vector
would be evaluated, which would mean that x
it would have to be resolved. But you don't want to x
be allowed, you want to be bound.
Look at the source for the macrolet
(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 will notice that the argument is bindings
not evaluated when the macro tries to ensure that the correct arguments have been supplied to it via assert-args
.
At the moment when clojure estimates (vector? bindings)
, bindings
- a form of ( list
) comprising fn
, as a first element, followed by arguments and, therefore, is not vector
at this point.
let
a vector is required for bindings (at compile time), so trying to put the vector function call in its place won't work (as it will only result in a vector at runtime).
However, you can make your own with a bit of macro fu:
(defmacro mylet [bindings & exprs]
`(let ~(vec bindings) ~@exprs))
(mylet (x 1) (inc x))
=> 2
This code, for example, works:
(eval `(let ~(vector 'a 1) (println ~'a)))
which means you can write your own let macro that takes a list instead of a vector. This would be nice for your general Clojure experience, and I would not recommend it.