开发者

clojure.core/or partial function works well with first argument but not with second

(defn divisible [x y] (zero? (rem x y)))

  1. ((or (fn [x] (divisible 开发者_高级运维x 3)) (fn [x] (divisible x 5))) 3)
  2. ((or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 5)

the first expression evals to true but not the second one why?

  • can some on explain whats going on here?


An expression of the form (or foo bar) does not "glue together" two predicates into one compound predicate; it returns foo if it is truthy, else bar. In your code, (fn [x] (divisible x 3)) is of course truthy (the only falsey values are false and nil), so the whole thing is equivalent to

((fn [x] (divisible x 3)) 3)
((fn [x] (divisible x 3)) 5)

What you want to do is something like

(some #(apply % 3) [(fn [x] (divisible x 3)) (fn [x] (divisible x 5)])
(some #(apply % 5) [(fn [x] (divisible x 3)) (fn [x] (divisible x 5)])
              ; ^- here goes the thing being tested

In general,

(defn or-preds [& preds]
  (fn [& args]
    (some #(apply % args) preds)))

((or-preds (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 3)
((or-preds (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) 5)
;; or simpler...
((or-preds #(divisible % 3) #(divisible % 5)) 3)


You seem to think that or somehow combines the functions that it receives as arguments, but that's not the case. or can take any kind of values as arguments and simply returns the first one that is "truthy".

So (or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) returns (fn [x] (divisible x 3)) (because functions are "not nothing" and thus "truthy").

So when you do ((or (fn [x] (divisible x 3)) (fn [x] (divisible x 5))) something), you're really just doing ((fn [x] (divisible x 3)) something).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜