为啥 let 需要一个向量?

Posted

技术标签:

【中文标题】为啥 let 需要一个向量?【英文标题】:Why does let require a vector?为什么 let 需要一个向量? 【发布时间】:2011-04-21 01:26:49 【问题描述】:

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

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

为什么会这样?

【问题讨论】:

我想这纯粹是为了可读性,而 let 强制执行向量只是确保保留成语。 (几乎所有“let”和“with-”宏都需要文字向量。) 这有点像自然法则。你可以推理那个它是那样的,但不能为什么。这个决定的真正原因是否是可读性、某些方案的实施、惯例或 Rich 那天吃的早餐类型仍然是未知数。能回答这个问题的,只有里奇本人。对于 Clojure,我们处于一个幸运的位置,对于宇宙来说...... 【参考方案1】:

我想主要是可读性。每当在 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

【讨论】:

我投票支持这个答案,因为它比我的答案快 2 分钟 并且 有代码!好节目! 没错,Hickey 在他的...并发演讲中提到了可读性原因,我认为是。 使用文字向量也清楚地表明它不是函数调用。 list-let 有效,但您必须知道第一个列表未正常评估。一旦你掌握了文字向量语法,你不妨利用它。 我倾向于在需要时在宏中写 [~@bindings] 而不是 ~(vec binding)。我发现它更容易阅读。 Hamish:他的并发演讲? Rich 上一次谈论不涉及并发的事情是什么时候? :-)【参考方案2】:

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

在 Clojure 中,圆括号和方括号的含义不同,但它们在绑定声明中的使用方式相同。

【讨论】:

【参考方案3】:

Clojure 非常努力地保持一致性。没有技术原因不能在letfnwith-open 等中使用列表表单。事实上,您可以很容易地创建自己的my-let 来代替使用一个。然而,除了明显突出之外,该向量在表单中始终如一地使用以表示“这里有一些绑定”。您应该努力在自己的代码中维护这一理想。

【讨论】:

【参考方案4】:

我猜这是约定

fn 用过,defn 用过,loop 用过。

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

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

【讨论】:

【参考方案5】:

另一种思考方式是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))

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

【讨论】:

以上是关于为啥 let 需要一个向量?的主要内容,如果未能解决你的问题,请参考以下文章

当我们已经拥有更强大的向量时,为啥还需要堆栈?

为啥我不能在 Swift 中使用 let in 协议?

为啥箭头函数名称必须是 const/let?

React.js 和 webpack - 为啥它不允许 var、let、const?

为啥vue要使用 let that = this

为啥需要两个范围 for 循环来更改 C++ 中向量的这些元素?