18

我正在享受 clojure 的乐趣,并且想知道 _ 语法在函数参数向量中的作用。

例子:

(def available-processors
    (.availableProcessors (Runtime/getRuntime)))

(prn "available processors: " available-processors)

(def pool
    (Executors/newFixedThreadPool (+ 2 available-processors)))

(defn dothreads!
    [func & {thread-count :threads exec-count :times :or {thread-count 1 exec-count 1}}]
    (dotimes [t thread-count]
        (.submit pool #(dotimes [_ exec-count] (func)))))

表格中的下划线是做什么的:

#(dotimes [_ exec-count] (func))
4

3 回答 3

19

我相信按照惯例,下划线在 Clojure 中用作必需但未使用的参数的占位符。正如基思·班纳特所说:

在 Clojure 中,下划线习惯性地用于指示它所标识的参数随后不会使用。

您的示例与此“用法”一致,因为dotimes不需要作为索引器的第一个参数,但表单需要绑定。

于 2013-04-15T17:09:21.703 回答
12

它没有什么特别之处,它只是命名你不关心的东西的约定,但它仍然是一个名称,可以像普通名称一样使用。

(defn hello [_] (+ 1 _))
(hello 10)

更新

这样做:

(defn hello [a a]  (+ a a))

不会产生错误,因此您可以使用任意数量的 _ ;)。

注意:Scheme 或 CL 的情况并非如此......嗯,那么在 clojure 中它背后的原因是什么???

于 2013-04-15T16:35:24.177 回答
0

以前的答案很好,但是由于我需要一些额外的说明,所以这是我的答案。

(defn blah[_] (str "the value you sent is " _)

等同于

(defn blah[my-arg] (str "the value you sent is " my-arg)

没有区别。_ 只是让查看代码的人知道该参数不打算使用的一种方式。

因此,例如,这在编程上很好:

(dotimes [_ 5] (println (str "I'm going to print this 5 times, and this is index # " _)))

但是查看代码的人会认为您不打算使用 _。因此,为了清楚起见,最好使用“n”或“ind”或其他任何东西,而不是_。如果您不使用该值,如下所示...

(dotimes [_ 5] (println "I'm going to print this 5 times"))

然后它将您的参数绑定到_,因为您表明您没有使用它。

最后一件事,如果绑定具有相同的名称,则最后一个获胜。所以下面会打印“4last4last4last4last”。

(defn will-print [_ a _ a _ a _ a] (println (str _ a _ a _ a _ a)))
(will-print 1 "a" 2 "b" 3 "c" 4 "last")

所以在 println 块中,'_' 绑定到 4,'a' 绑定到 'last'。所有先前发送的值都被忽略/覆盖。

于 2018-07-10T18:32:49.490 回答