简体   繁体   English

减少clojure。 无起始值,空集合

[英]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]: IFnIFn函数的Java接口

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM