(filter #(zero? (mod % 7)) (range 1 3))
this,产生一个空序列。
但是,调用 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的区别。
它们是两个完全不同的概念,但是,在下面的例子中,当与 max 结合时,它们都做同样的工作。
让xs 是任何数字的集合。
(apply max xs) 等于 (reduce max xs)
申请
通常使用多个参数调用函数,因此可以像这样调用 max:(max 3),或 (max 5 9),或 (max 4 1 3) ... 如前所述:just (max ) 将是一个例外。
Apply 然而,允许某人调用一个以集合形式传递参数的函数。所以对应于最后一个例子,以下是可能的:(apply max [3]), or (apply max [5 9]), or (apply max [4 1 3]) ... Just (apply max [] ) 甚至 (apply max) 会导致与上述相同的异常。这在很多情况下都很有用。
减少
对比减少有点棘手。除了 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)
这同样适用于最大值。在每次迭代中,将当前项目的值与备忘录进行比较。每次将最大值保存到备忘录中:因此,本例中的备忘录表示“迄今为止的最大值”。
所以(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)) 占用的时间并没有显着差异。无论如何,应用解决方案对我来说看起来更容易,但这只是我的意见。