如果我运行此代码,我将收到错误" ArityException错误的args(0)传递给:core / max"
(apply max (filter #(zero? (mod % 7)) (range 1 3)))
但是,如果我运行此代码
(apply max (filter #(zero? (mod % 7)) (range 1 10)))
然后我得到结果7。
有没有人可以帮我解决这个问题?
答案 0 :(得分:3)
(filter #(zero? (mod % 7)) (range 1 3))
这样,产生一个空序列。
但是,必须使用至少一个参数调用max。当你对它应用一个空序列时,它会被零参数调用,这会产生arity异常。
你可以这样做:
(defn my [a b]
(let [result (filter #(zero? (mod % 7)) (range a b))]
(if (zero? (count result))
nil ; or 0 or.. whatever
(apply max result))))
申请并减少
因为问题出现了,这里是对apply和reduce之间区别的简短解释。
它们是两个完全不同的概念,但是,在以下情况下,当与最大值组合时,两者都做同样的工作。
让xs
成为任何数字集合。
(apply max xs)
等于(reduce max xs)
应用强>
通常使用多个参数调用函数,因此可以像这样调用max:(max 3),或(max 5 9),或(max 4 1 3)......如前所述:just(max )将是一个arity例外。
然而,应用,让某人调用以集合形式传递参数的函数。因此,与最后一个示例相对应,以下是可能的:(应用max [3]),或(应用max [5 9])或(应用max [4 1 3])... Just(apply max [] )或甚至(应用最大值)将导致与上述相同的arity例外。这在许多情况下很有用。
<强>减少强>
相反减少有点棘手。除了map和filter之外,它对Clojure等函数式编程语言也是绝对必要的。
reduce的主要思想是遍历一个集合,在每个步骤中处理当前项目所需的信息并将其添加到备忘录或累加器中。
说,想要找出集合中所有数字的总和。
让xs
成为[3 4 5 23 9 4]
。
(reduce + xs)
可以胜任。
更明确地可以写:(reduce (fn [memo value] (+ memo value)) xs)
作为reduce的第一个参数传递的函数需要两个参数:第一个是备忘录,第二个是集合中当前项的值。现在为集合中的每个项调用该函数。函数的返回值保存为备忘录
注意:集合的第一个值用作备忘录的初始值,因此迭代从集合的第二个值开始。这是它正在做的事情:
(+ 3 4) ; memo is 7 now
(+ 7 5) ; memo is 12 now
(+ 12 23) ; memo is 35 now
(+ 35 9) ; memo is 44 now
(+ 44 4) ; memo is 48 now
(还有一种方法可以指定备忘录的起始值,有关详细信息,请参阅clojuredocs.org)
这与max相同。在每次迭代中,将当前项的值与备忘录进行比较。每次将最高值保存到备忘录时:因此,此案例中的备忘录代表“迄今为止的最大值”。
所以(reduce max [4 1 3 5 2])
计算如下:
(max 4 1) ; memo is 4
(max 4 3) ; memo is 4
(max 4 5) ; memo is 5
(max 5 2) ; memo is 5
<强>所以吗
现在使用哪一个?它表明(reduce max (range 100000000))
和(apply max (range 100000000))
所用的时间并没有显着差异。无论如何,应用解决方案对我来说更容易,但这只是我的意见。
答案 1 :(得分:2)
在1和3之间没有可被7整除的数字,第一个示例中的过滤结果返回一个空序列,这意味着调用(apply max [])
的第一个示例与调用{{1}相同}}。 max至少需要一个参数,因此需要(max)
。
修复它的几个选项:
ArityException
或
(last (filter #(zero? (mod % 7)) (range 1 3))
答案 2 :(得分:0)
根据错误消息,传递给max
的参数数量为0,这是错误的。我想这是有道理的,因为无法计算空列表的最大值。
max没有参数的原因是没有数字在1和3之间被7整除。