clojure.core/or partial function works well with first argument but not with second
(defn divisible [x y] (zero? (rem x y)))
- ((or (fn [x] (divisible 开发者_高级运维x 3)) (fn [x] (divisible x 5))) 3)
- ((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)
.
精彩评论