Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you compose two or more predicates in clojure?

Tags:

clojure

I want to apply two (or more) predicates to a single value. For example, say I want to test if a value is a positive integer:

(defn posint? [n]
   (and (integer? n) (pos? n)))

That does it, but what if I want to compose the predicates applied? I don't want to write a function for each possible combination of predicates.

like image 907
stand Avatar asked Oct 27 '11 21:10

stand


3 Answers

In Clojure 1.3 there is actually a built-in function called every-pred to do just this. See here.

(defn posint? [n]
  ((every-pred integer? pos?) n))
like image 83
Julien Chastang Avatar answered Oct 18 '22 10:10

Julien Chastang


If you want to compose them in an and relationship, use every-pred:

((every-pred pos? even?) 5)
;false
((every-pred pos? even?) 6)
;true
((every-pred pos? even?) -2)
;false

And if you want to compose them in an or relationship, use some-fn:

((some-fn pos? even?) 5)
;true
((some-fn pos? even?) 6)
;true
((some-fn pos? even?) -2)
;true
((some-fn pos? even?) -3)
;false
like image 36
Didier A. Avatar answered Oct 18 '22 11:10

Didier A.


If you're looking to do these checks inline, the following may be what you are looking for.

(defn predicate-test [fns t]
    "test all predicates against value t and return true iff all predicates return true."
    (every? true? ((apply juxt fns) t)))

(predicate-test [integer? pos?] 4)

You could then create named versions for your most used predicate tests:

(def posint? (partial predicate-test [integer? pos?])

(posint? 4)
like image 3
jurgns Avatar answered Oct 18 '22 10:10

jurgns