代替
(let [x 1] (my-expression))
我正在尝试使用:
(let (vector x 1) (my-expression))
不要问为什么,我只是更喜欢普通的括号。但是 Clojure 说:
let requires a vector for its binding in ...
怎么了?
代替
(let [x 1] (my-expression))
我正在尝试使用:
(let (vector x 1) (my-expression))
不要问为什么,我只是更喜欢普通的括号。但是 Clojure 说:
let requires a vector for its binding in ...
怎么了?
查看宏的来源let
(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))
您会注意到,bindings
当宏试图确保通过assert-args
.
在 clojure 计算时(vector? bindings)
,bindings
是一个表单 ( list
),其中包含 afn
作为第一个元素,后跟它的参数,因此此时不是 a vector
。
let
它的绑定需要一个向量(在编译时),因此试图将向量函数调用放在它的位置是行不通的(因为这只会在运行时产生一个向量)。
但是,您可以使用一些宏来制作自己的 let:
(defmacro mylet [bindings & exprs]
`(let ~(vec bindings) ~@exprs))
(mylet (x 1) (inc x))
=> 2
例如,此代码确实有效:
(eval `(let ~(vector 'a 1) (println ~'a)))
这意味着您可以编写自己的 let 宏来接受列表而不是向量。这对您的整体 Clojure 体验非常不利,我不建议这样做。