3

我有这个 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?)

=>(真假真)

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

=> 假的

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

=> 真

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

4

4 回答 4

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?,以便它s作为多个参数而不是单个列表传递的内容(通过使用apply)。

于 2012-08-25T06:54:56.530 回答
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]
于 2012-08-25T11:26:57.860 回答
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))
于 2012-08-25T06:58:20.657 回答
0

您还可以像下面这样定义您的函数以使其更清晰。

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

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

于 2012-08-25T07:20:22.380 回答