clojure部分澄清

clojure部分澄清,clojure,functional-programming,jvm,read-eval-print-loop,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-i

我正在读一本关于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
定义, 和
重复
定义和语法。部分

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.

那么这是如何适应的呢?

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可以更好地说明其功能:

(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。否则,我个人倾向于使用匿名函数读取器表单
#(…)

partial
实际上不检查它的第一个参数支持哪些算术;一个可能更准确的docstring会说它“接受一个函数f和一些参数到f”。(很明显,如果您提供的参数太多,结果部分应用的函数将被破坏,尽管只有在您尝试调用它时才能观察到。)这就是为什么
(部分rand int 10)
是可以的,即使
rand int
提供的参数数量不“少于正常值”

这里之所以需要
部分
或类似的
#(rand int 10)
,是因为
反复
期望它的最终参数是一个可以反复调用的函数,而
(rand int 10)
则是一个数字


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

重复
我们感兴趣的签名:
(重复编号函数)

在本例中,partial将简单地将
rand int 10
包装成一个函数,该函数可由外部函数返回并使用,在本例中,
会反复使用


如果没有
partial
(或
#
内部表达式在外部表达式之前解析(也有例外,但现在让我们保持简单),因此当在没有
partial
的情况下重复调用
时,将传递给它的是
rand int
的返回值,这是
Int
而不是一个函数。

是的,我认为这在语义上是更合适的解决方案。ThanksI认为问题在于
(rand int 10)
返回一个数字<从语义上看,code>#()
显然是一个更好的解决方案