为什么要求矢量?

时间:2010-10-04 22:58:50

标签: macros clojure lisp let

在我向不熟悉clojure的同事解释一些clojure代码之前,我从未真正考虑过这个问题。当他问你为什么使用向量来声明绑定而不是列表时,我向他解释let。我对他没有真正的答案。但语言确实限制您使用列表:

=> (let (x 1) x)
java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:0)

为什么会这样?

5 个答案:

答案 0 :(得分:25)

我想象的大部分是可读性。无论何时在Clojure中需要绑定,都会使用矢量。很多人都认为绑定的向量可以使事情更好地流动,并且更容易识别绑定是什么以及正在运行的代码是什么。

只是为了好玩:

user=> (defmacro list-let [bindings & body] `(let ~(vec bindings) ~@body))
#'user/list-let
user=> (macroexpand-1 '(list-let (x 0) (println x)))
(clojure.core/let [x 0] (println x))
user=> (list-let (x 0 y 1) (println x y))
0 1
nil

答案 1 :(得分:13)

这是Scheme的成语。在许多Scheme实现中,方括号可以与列表文字中的圆括号互换使用。在那些Scheme实现中,方括号通常用于区分参数列表,参数列表和S表达式或数据列表中的绑定。

在Clojure中,括号和括号表示不同的内容,但它们在绑定声明时的使用方式相同。

答案 2 :(得分:11)

Clojure非常努力地保持一致。没有技术原因,列表表单无法在letfnwith-open等中使用...事实上,您可以创建自己的my-let很容易使用一个而不是。然而,除了明显突出外,矢量在形式上一致地使用意味着“这里有一些约束”。你应该努力在你自己的代码中坚持这个理想。

答案 3 :(得分:1)

我的猜测是一个约定

fn使用了它,defn使用了它,loop使用了它。

它似乎适用于所有类似于具有某些参数的代码块的内容;更具体地说,方括号用于标记那些参数

代码块的其他形式不使用它,例如ifdo。他们没有任何参数

答案 4 :(得分:1)

另一种思考方式是let只是从lambda派生而来。这两个表达式是等价的:

((fn [y] (+ y 42)) 10)
(let [y 10] (+ 42 y))

因此,作为学术或教学点,您甚至可以编写自己的let非常基本的版本,其中包含列表和矢量:

(defmacro my-let [x body]
  (list (list `fn[(first x)]
              `~body)
        (last x)))

(my-let (z 42) (* z z))

虽然没有实际的理由这样做。