这个Clojure代码中的bug在哪里?

时间:2012-08-25 06:47:17

标签: clojure

我有这个Clojure代码:

(defn apply-all-to-arg [& s]
    (let [arg (first s)
          exprs (rest s)]
        (for [condition exprs] (condition arg))))

(defn true-to-all? [& s]
    (every? true? (apply-all-to-arg s)))

这是测试代码:

(apply-all-to-arg 2 integer? odd? even?)

=> (true false true)

(every? true? (apply-all-to-arg 2 integer? odd? even?)

=>假

(true-to-all? 2 integer? odd? even?)

=>真

我的问题是: 为什么功能真实?返回true(它必须返回false)

4 个答案:

答案 0 :(得分:3)

true-to-all?使用单个参数apply-all-to-arg调用s。所以你不是在呼叫(every? true? (apply-all-to-arg 2 integer? odd? even?),而是在呼叫:

(every? true? (apply-all-to-arg (list 2 integer? odd? even?))

因此,在apply-all-to-arg中,arg的值将为该列表,exprs的值将为空列表。因为无论条件是什么,every?对于空列表都是正确的,所以你会得到回报。

要解决此问题,您可以更改apply-all-to-arg,以便它接受列表而不是可变数量的参数,或者您可以更改true-to-all?,以便它传递{{1}的内容作为多个参数而不是单个列表(通过使用s)。

答案 1 :(得分:2)

创建一个将多个函数并行应用于一个参数的函数的默认Clojure函数是juxt:

=> ((juxt integer? odd? even?) 2)
[true false true]

=> (every? true? ((juxt integer? odd? even?) 2))
false

=> (defn true-to-all? [a & fns]
     (every? true? ((apply juxt fns) a)))

=> (true-to-all? 2 integer? odd? even?)
false

如果与juxt结合使用的函数都采用多个参数,那么它也能正常工作

=> ((juxt + - / *) 6 3)
[9 3 2 18]

答案 2 :(得分:0)

因为当您致电true-to-all?时,参数s就是一个列表,因此您实际上正在调用(apply-all-to-arg '(2 integer? odd? even?))

尝试像这样定义true-to-all?

(defn true-to-all? [& s]
  (every? true? (apply apply-all-to-arg s))

答案 3 :(得分:0)

您还可以像下面一样定义您的功能,以使其更清晰。

(defn apply-all-to-arg [v & fns] 
       (map #(% v) fns))

因为这使得函数定义清楚,它需要一个值和可选函数来应用于该值。