clojure部分澄清

ton*_*o.j 7 jvm functional-programming clojure 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)
Run Code Online (Sandbox Code Playgroud)

我的问题是:为什么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.
Run Code Online (Sandbox Code Playgroud)

那么它如何适应?

Art*_*ldt 10

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

在这种情况下

user> (repeatedly 10 (partial rand-int 10))
(3 1 3 6 1 2 7 1 5 3)
Run Code Online (Sandbox Code Playgroud)

相当于:

user> (repeatedly 10 #(rand-int 10))                        
(9 5 6 0 0 5 7 6 9 6)
Run Code Online (Sandbox Code Playgroud)

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

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

(partial + 4)
Run Code Online (Sandbox Code Playgroud)

产生相当于:

(fn [& unfixed-args] (apply + (concat [4] unfixed-args)))
Run Code Online (Sandbox Code Playgroud)

(它不从字面上产生此)的想法是建立一个函数,未固定的参数,与固定的人结合了他们,并要求你传递给函数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   
Run Code Online (Sandbox Code Playgroud)

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


Mic*_*zyk 6

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

之所以需要partial这样或类似的原因#(rand-int 10)repeatedly期望它的最终参数是一个可以反复调用的函数,而它(rand-int 10)是一个数字.

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