我正在阅读 The Joy of Clojure ,在有关并行化的部分中,对函数 pvalues
、pmap
和 pcalls
进行了解释,并提供了每个函数的用法的简短示例。以下是针对 pvalues
和 pcalls
给出的示例:
(defn sleeper [s thing] (Thread/sleep (* 1000 s)) thing)
(pvalues
(sleeper 2 :1st)
(sleeper 3 :2nd)
(keyword "3rd"))
(pcalls
#(sleeper 2 :1st)
#(sleeper 3 :2nd)
#(keyword "3rd"))
我理解两者之间的技术差异——pvalues
需要计算可变数量的“值”,而 pcalls
需要“任意数量的函数”没有参数,”被并行调用。在这两种情况下,都会返回结果的惰性序列。
我的问题本质上是,您什么时候会使用一个与另一个?似乎唯一的语义区别是您在每个参数之前都添加了一个 #
给 pcalls
,将它变成一个匿名函数。因此,纯粹从节省击键和简化代码的角度来看,只使用 pvalues
不是更有意义吗? -- 如果是这样,为什么还要有一个 pcalls
函数?
我用 pcalls
得到了它,你可以用一个符号来代替一个函数,但是如果你想用 pvalues
使用这样的函数,你可以把括号中的函数,以便调用它。
我对为什么 Clojure 具有这两个如此相似的函数感到有点困惑。有没有什么你可以用一个,但不能用另一个?一些人为的示例可能会有所帮助。
最佳答案
pvalues 是一个围绕 pcalls 的便捷宏,尽管因为宏不是一流的,它不能像函数那样组合或传递。这是一个只有 pcalls 有效的例子:
user> (defn sleeper [s thing] (Thread/sleep (* 1000 s)) thing)
#'user/sleeper
user> (def actions [#(sleeper 2 :1st) #(sleeper 3 :2nd) #(keyword "3rd")])
#'user/actions
user> (apply pcalls actions)
(:1st :2nd :3rd)
user> (apply pvalues actions)
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/pvalues, compiling:(NO_SOURCE_PATH:1:1)
在 clojure 中设计 API 时,不要限制用户只能通过宏与您的库进行交互,这一点很重要,因为这样他们就会遇到诸如此类的限制。
关于multithreading - Clojure:pvalues 与 pcalls,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21340186/