[英]clojure reduce. no start value, empty collection
In a riddle I have to complete the following expressions in order to evaluate to true. 在一个谜语中,我必须完成以下表达式才能评估为真。 There must be one single insertion, which fits to all of them.
必须有一个适合所有插入的单个插入。
(= 15 (reduce __ [1 2 3 4 5]))
(= 0 (reduce __ []))
(= 6 (reduce __ 1 [2 3]))
The third expression provides a start value. 第三个表达式提供一个起始值。 Hence my replacement cannot provide another one.
因此,我的替代人不能提供另一个。
This function would pass the first and the third truth test: 此函数将通过第一个和第三个真相测试:
#(+ %1 %2)
However, the second expression yields the following error: 但是,第二个表达式产生以下错误:
clojure.lang.ArityException: Wrong number of args (0) passed to (...my function id) clojure.lang.ArityException:传递给(...我的函数ID)的args(0)数量错误
It looks like usually reduce calls the given function only if the length of start value + collection is bigger than 2. If this length is 0, like in the case above, it is called as well - with 0 arguments. 看起来通常只有在起始值+集合的长度大于2的情况下,reduce才会调用给定函数。如果该长度为0(如上述情况),则也会调用它-使用0参数。
Does anyone have a hint how to carry on here? 有人暗示如何进行吗?
From the comments, the solution is clearly +
, but maybe it's valuable to look at it in some detail to see why . 从评论来看,解决方案显然是
+
,但也许有必要对其进行详细研究以了解其原因 。 As it turns out, there's a lot to it. 事实证明,有很多事情要做。
First, let's look at reduce to see what the requirements are: 首先,让我们看一下reduce ,看看需求是什么:
(defn reduce
"f should be a function of 2 arguments. If val is not supplied,
returns the result of applying f to the first 2 items in coll, then
applying f to that result and the 3rd item, etc. If coll contains no
items, f must accept no arguments as well, and reduce returns the
result of calling f with no arguments. ..."
...
([f coll]
(if (instance? clojure.lang.IReduce coll)
(.reduce ... coll f)
...))
([f val coll]
(if (instance? clojure.lang.IReduceInit coll)
(.reduce ... coll f val)
...)))
This is a multi-arity function that either takes a function and a collection, or a function, initial value and a collection. 这是一个多函数函数,它要么接受一个函数和一个集合,要么接受一个函数,初始值和一个集合。
+ is also a multi-arity function that behaves depending on how many arguments you pass to it. +也是一个多函数函数,其行为取决于传递给它的参数数量。 The source below (edited for the parts we care about), shows reduce is satisfied by 0-arity and 2-arity.
下面的源代码(针对我们关心的部分进行了编辑)显示,reduce由0-arity和2-arity满足。
(defn +
"Returns the sum of nums. (+) returns 0..."
...
([] 0)
...
([x y] (. clojure.lang.Numbers (add x y)))
...
Clearly (reduce + [])
calls the first clause and returns 0. Test 2 is explained. 显然
(reduce + [])
调用第一个子句并返回0。将说明测试2。
This works for the first test by applying the add function to each pair of Numbers, which happens in the Java internals for Clojure , in a tight for
loop. 这适用于第一次测试,方法是将add函数应用到每对Numbers, 这在紧密的
for
循环中发生在Clojure的Java内部中。
The final test works exactly like the first, except it calls the [v val coll]
implementation of reduce. 最终测试与第一个测试完全相同,只是它调用了reduce的
[v val coll]
实现。 This applies a slightly different internal function , but with the same effect. 这会应用稍微不同的内部功能 ,但效果相同。
Notes 笔记
[1]: IFn
is the Java interface for clojure functions [1]:
IFn
是IFn
函数的Java接口
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.