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.否则,我个人倾向于使用匿名函数阅读器表单#( ... )
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)
返回的序列的每个项单独调用,因此您将从中获得一系列(可能是不同的,独立的)随机数.