clojure部分澄清

时间:2013-04-13 00:19:55

标签: clojure functional-programming jvm read-eval-print-loop

我正在读一本关于clojure的书,我来的是一个我不完全理解的例子。

以下是repl中的代码:

user=> (repeatedly 10 (rand-int 10))
ClassCastException java.lang.Integer cannot be cast to clojure.lang.IFn  clojure.core/repeatedly/fn--4705 (core.clj:4642)

user=> (repeatedly 10 (partial rand-int 10))
(5 0 5 5 2 4 8 8 0 0)

我的问题是: 为什么这里需要partial,以及它如何适合partial定义, 和repeatedly定义&句法。部分......

Takes a function f and fewer than the normal arguments to f, and
  returns a fn that takes a variable number of additional args. When
  called, the returned function calls f with args + additional args.

那么这又如何适应呢?

3 个答案:

答案 0 :(得分:10)

Partial只是一种更简单的方法来定义一个匿名函数,该函数修复函数的一些参数,然后将其余参数从参数传递给创建的函数。

在这种情况下

user> (repeatedly 10 (partial rand-int 10))
(3 1 3 6 1 2 7 1 5 3)

相当于:

user> (repeatedly 10 #(rand-int 10))                        
(9 5 6 0 0 5 7 6 9 6)

Partial在这里用词不当,因为partial被用于事先将所有参数(或者更确切地说是唯一的参数)修复为rand-int。

更多的局部使用部分说明了它的功能更好:

(partial + 4)

产生相当于:

(fn [& unfixed-args] (apply + (concat [4] unfixed-args)))

(它不会产生这种情况) 我们的想法是构建一个接受未修复参数的函数,将它们与固定参数组合在一起,并调用传递给partial的函数,并使用足够的参数来正常工作。

user> ((fn [& unfixed-args] (apply + (concat [4] unfixed-args))) 5 6 7 8 9)       
39
user> ((partial + 4) 5 6 7 8 9)
39   

当参数的数量可变时,我只在实践中使用partial。否则,我个人倾向于使用匿名函数阅读器表单#( ... )

答案 1 :(得分:6)

partial实际上并没有检查它的第一个参数支持哪个arities;一个可以说是更准确的docstring会说它“需要一个函数f和f的一些参数”。 (显然,如果你提供了太多的参数,那么结果部分应用的函数将被破坏,但是当你试图调用它时,这只会是可观察的。)所以即使(partial rand-int 10)的参数数量为rand-int也是如此。提供的{1}}并非“少于正常”。

此处需要partial或类似#(rand-int 10)之类的原因是repeatedly期望其最终参数是可以重复调用的函数,而(rand-int 10)将是一个数字。

将此与repeat进行比较,后者返回一个序列,其中所提供的项重复指定的次数(或在一元情况下无限次多次)。这里(rand-int 10)是一个合适的第二个参数,但当然它会是一个特定的数字,所以结果看起来像(8 8 8 8 8 ...);对于返回的序列中的每个项,repeatedly将单独调用(partial rand-int 10),因此您将从中获得一系列(可能是不同的,独立的)随机数。

答案 2 :(得分:0)

我们感兴趣的

repeatedly签名:(repeatedly number function)

在这种情况下,partial将简单地将rand-int 10包装到一个可以由外部函数(在这种情况下为repeatedly返回和使用的函数中)。

没有partial(或#内部表达式先于外部表达式解析(有例外,但现在让我们保持简单),所以当{{ 1}}是在没有repeatedly的情况下调用的,将传递给它的是返回值partial,即rand-int而不是函数。