尝试理解Clojure中的"let"示例

14
(defn make-adder [x]
  (let [y x]
    (fn [z] (+ y z))))
(def add2 (make-adder 2))
(add2 4)
-> 6

我正在尝试理解Clojure中的let示例。变量y是什么,它似乎从未被设置为任何值。我不理解let语法。


它将 y 绑定到 x - Barmar
1
啊,谢谢,现在明白了。 - eat_a_lemon
3
一个学究式的观点,y不是一个变量,因为它的值永远不会变化。在Clojure中有“vars”,但它们很少用于let绑定(这里的defn创建了一个名为“make-adder”的var,它和add2是此处仅显示的唯二变量)。 - noisesmith
这个代码示例实际上来自 https://clojure.org/about/functional_programming,在“一等函数”下的最后一个代码片段。 - alichaudry
3个回答

19
(let [y x]
    <body>)

在一个词法环境中,y被绑定到x的值,评估<body>

有关let语法,请参见Clojure文档。其一般形式为:

(let [sym1 val1
      sym2 val2
      sym3 val3
      ... ]
    <body>)

每个 symN 都绑定到相应的 valN


1
一个小问题:你这里的命名有误导性,除非valN是var类型,否则没有任何varN是var。 - noisesmith
1
谢谢,这是我之前不知道Lisp和Clojure之间的区别。我已经更新了我的答案以使用symN代替。 - Barmar

11

这个函数:

(defn make-adder [x]
  (let [y x]
    (fn [z] (+ y z))))

它本身返回一个一等函数(一个像任何其他值一样可以返回、传递和分配名称的函数)。在let内部,x绑定到y,因此上面的函数等效于下面的函数:

(defn make-adder [x]
  (fn [z] (+ x z)))

因此,当调用具有值2make-adder时,它将返回此一等函数:

(fn [z] (+ 2 z))

记住,一等函数可以被赋值给一个名称,就像这行代码:

(def add2 (made-adder 2))

因此,上面的那行代码与以下代码等效:

(def add2 (fn [z] (+ 2 z)))

因此,它与以下代码等效:

(defn add2 [z] (+ 2 z))

这意味着当调用add2时:

(add2 4)

上述表达式的计算结果为:

(+ 2 4)

这将评估为6


1
回答非常详细,但其中90%与他的问题无关,他的问题只是关于 y - Barmar
正确。我想要完整地解释这个例子。 - djhaskin987
+1 感谢您的回答。我来到SO是因为文档对我来说不够清晰,虽然这里的let解释有所欠缺,但这是对问题中代码片段中非let部分的很好的解释。 - alichaudry

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接