Clojure:pvalues与pcalls

时间:2014-01-24 18:50:52

标签: multithreading clojure parallel-processing concurrent-programming

我正在阅读The Joy of Clojure,在有关paralellization的部分中,解释了函数pvaluespmappcalls,并简要介绍了每个函数用来。以下是pvaluespcalls

的示例
(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有这两个相似的功能。有什么可以用一个而不是另一个吗?一些人为的例子可能会有所帮助。

1 个答案:

答案 0 :(得分:6)

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时,重要的是不要限制用户只通过宏与您的库进行交互,因为它们会受到诸如此类的限制。