【问题标题】:ArityException Wrong number of args (0) passed to: core/maxArityException 传递给的 args (0) 数量错误:core/max
【发布时间】:2016-01-26 02:46:32
【问题描述】:

如果我运行这段代码,我会得到一个错误“ArityException Wrong number of args (0) passed to: core/max”

(apply max (filter #(zero? (mod % 7)) (range 1 3)))

但是,如果我运行这段代码

(apply max (filter #(zero? (mod % 7)) (range 1 10)))

然后我得到结果 7.

有没有人可以帮我解决这个问题?

【问题讨论】:

    标签: clojure


    【解决方案1】:
    (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)) 占用的时间并没有显着差异。无论如何,应用解决方案对我来说看起来更容易,但这只是我的意见。

    【讨论】:

    • 非常感谢,安东!你知道“应用”和“减少”有什么不同吗?因为我在运行代码(应用最大结果)和(减少最大结果)时得到了相同的结果。谢谢!
    【解决方案2】:

    在 1 和 3 之间没有可被 7 整除的数字,第一个示例中的过滤器结果返回一个空序列,这意味着第一个示例如果调用 (apply max []) 与调用 (max) 相同。 max 至少需要一个参数,因此ArityException

    修复它的几个选项:

    (last (filter #(zero? (mod % 7)) (range 1 3))
    

    (if-let [by-7 (seq (filter #(zero? (mod % 7)) (range 1 3)))]
      (apply max by-7)
      nil ;; or whatever value in case the collection is empty
      )
    

    【讨论】:

      【解决方案3】:

      根据错误消息,传递给max 的参数数量为0,这是错误的。我想这是有道理的,因为不可能计算空列表的最大值。

      max 没有参数的原因是在 1 和 3 之间没有可以被 7 整除的数字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-10
        • 1970-01-01
        • 2016-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多