首页 文章

为什么要求矢量?

提问于
浏览
14

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

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

这究竟是为什么?

5 回答

  • 25

    考虑这一点的另一种方法是 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))
    

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

  • 13

    我想,大部分是可读性 . 每当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
    
  • 11

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

  • 1

    我的猜测是这是一个惯例

    fn 使用它, defn 使用它, loop 使用 .

    它似乎适用于所有类似于具有一些参数的代码块的东西;更具体地说,方括号用于标记这些参数

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

  • 1

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

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

相关问题