Clojure

Add any-pred and every-pred combinators

Details

  • Type: Enhancement Enhancement
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: Release 1.3
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code and Test
  • Approval:
    Ok

Description

Per the discussion at http://groups.google.com/group/clojure-dev/browse_frm/thread/899349c6a9b526e0

There is a general interest in a set of functions named any/every-pred that take a set of predicates and return a function that applies logical AND/OR to the application of each of its args. The naive implementations would be:

(defn every-pred [& preds] 
  (fn [& args] (every? #(every? % args) preds))) 

((every-pred pos? even?) 1 3 5 7 9)
;=> false

((every-pred pos? odd?) 1 3 5 7 9)
;=> true

(defn any-pred [& preds] 
  (fn [& args] (some #(some % args) preds)))

((any-pred pos? even?) -1 2 3 4 5 6)
;=> true

However, these implementations fall down in the following ways and should be corrected before inclusion to clojure.core:

1) The functions returned by each do not adhere to the same results as (and) and (or) given no arguments.

2) They and their returned functions assume varargs in every call. should be variadically unrolled in much the same way as juxt and comp. A longer term solution would be to implement them in terms of a macro that performs the unrolling automatically, but that is "extra-credit".

3) They should be tested in other_functions.clj

Activity

Hide
Fogus added a comment -

Added a patch containing the variadic unwound versions of every-pred and any-pred and tests for each.

Show
Fogus added a comment - Added a patch containing the variadic unwound versions of every-pred and any-pred and tests for each.
Hide
Stuart Halloway added a comment -

One problem, and one question:

Problem: every-pred does not handler trueish arguments consistently.

((every-pred identity identity identity) 1 2)
=> 2

((every-pred identity identity identity identity) 1 2)
=> true

Since the name uses every, I think it should work like Clojure's every?, not like Clojure's and. Which raises the question about any-pred. If it is going to work like Clojure's some, shouldn't it be called some-pred?

I also found the docstrings confusing.

Show
Stuart Halloway added a comment - One problem, and one question: Problem: every-pred does not handler trueish arguments consistently.
((every-pred identity identity identity) 1 2)
=> 2

((every-pred identity identity identity identity) 1 2)
=> true
Since the name uses every, I think it should work like Clojure's every?, not like Clojure's and. Which raises the question about any-pred. If it is going to work like Clojure's some, shouldn't it be called some-pred? I also found the docstrings confusing.
Hide
Fogus added a comment - - edited

Problem: every-pred does not handler trueish arguments consistently.

Well, it consistently returns truthiness. I understand what you mean. There are at least two ways to handle this. Make every return filter through (boolean) or use every?/some in every case. Do you have a preference?

shouldn't it be called some-pred?

I buy that. Of course that might help to clarify my confusing docstrings (curse me for attempting an economy of verbiage).

Show
Fogus added a comment - - edited Problem: every-pred does not handler trueish arguments consistently. Well, it consistently returns truthiness. I understand what you mean. There are at least two ways to handle this. Make every return filter through (boolean) or use every?/some in every case. Do you have a preference? shouldn't it be called some-pred? I buy that. Of course that might help to clarify my confusing docstrings (curse me for attempting an economy of verbiage).
Hide
Rich Hickey added a comment -

every-pred should return a boolean by filtering through boolean

any-pred should be some-fn

Show
Rich Hickey added a comment - every-pred should return a boolean by filtering through boolean any-pred should be some-fn
Hide
Fogus added a comment -

Updated patch.

Show
Fogus added a comment - Updated patch.
Hide
Fogus added a comment -

Sorry it took me a while to get this in – I was a bit busy last week.

I modified the behavior of every/some-pred to return true or false and modified the tests to check this fact. Also simplified the docstrings. I could not delete the original patch, but since the attached files are sorted by date (and the new one is larger) it should be clear which is the valid patch file.

Show
Fogus added a comment - Sorry it took me a while to get this in – I was a bit busy last week. I modified the behavior of every/some-pred to return true or false and modified the tests to check this fact. Also simplified the docstrings. I could not delete the original patch, but since the attached files are sorted by date (and the new one is larger) it should be clear which is the valid patch file.
Hide
Stuart Halloway added a comment -

Third patch renames any-pred to some-fn to match Rich's naming suggestion.

Show
Stuart Halloway added a comment - Third patch renames any-pred to some-fn to match Rich's naming suggestion.
Hide
Rich Hickey added a comment -

It looks like the patches and comments got crossed in the mail:

fogus' 2/8 patch correctly coerced to boolean in every-pred, but erroneously did so for some-pred.

screened patch did not incorporate either, but changed name to some-fn

We need:

every-pred - coerces to boolean
some-fn - doesn't

Thanks!

Show
Rich Hickey added a comment - It looks like the patches and comments got crossed in the mail: fogus' 2/8 patch correctly coerced to boolean in every-pred, but erroneously did so for some-pred. screened patch did not incorporate either, but changed name to some-fn We need: every-pred - coerces to boolean some-fn - doesn't Thanks!
Hide
Fogus added a comment -

Let's try this again. All wires appear uncrossed.

Show
Fogus added a comment - Let's try this again. All wires appear uncrossed.
Hide
Rich Hickey added a comment -

doc-only changes:

some-fn doc says it returns true, when it actually returns the first logical true value returned by one of the fns. Also, we don't yet use truthy/falsey in Clojure docs, and I'm not sure I want to start now.

Thanks

Show
Rich Hickey added a comment - doc-only changes: some-fn doc says it returns true, when it actually returns the first logical true value returned by one of the fns. Also, we don't yet use truthy/falsey in Clojure docs, and I'm not sure I want to start now. Thanks
Hide
Fogus added a comment -

This has the docstring changes suggested by Rich (i.e. removing "truthy" "falsey" etc.).

Show
Fogus added a comment - This has the docstring changes suggested by Rich (i.e. removing "truthy" "falsey" etc.).

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: