conjoin and disjoin for core or contrib?

156 views
Skip to first unread message

Fogus

unread,
Jan 24, 2011, 10:35:48 AM1/24/11
to Clojure Dev
I've recently come across a need for conjoin and disjoin functions
implemented[1] as follows:

(defn conjoin
"Given a bunch of predicates, returns a function that is the logical
AND
of said functions against a bunch of values."
[& preds]
(fn [& args]
(every? (fn [arg]
(every? #(% arg)
preds))
args)))

(defn disjoin
"Given a bunch of predicates, returns a function that is the logical
OR
of said functions against a bunch of values."
[& preds]
(fn [& args]
(some (fn [arg]
(some #(% arg)
preds))
args)))

I might have lost my mind, but neither of these functions appear to
exist in core or contrib and I thought it might be worth floating them
out for general consumption to see if they might be useful inclusions
in one or the other. The problem in the case of contrib is that it's
unclear where they would fit.

Thanks.


[1]: Nicer formatting and examples at https://gist.github.com/790187

Baishampayan Ghose

unread,
Jan 24, 2011, 10:42:45 AM1/24/11
to cloju...@googlegroups.com

As a side effect of conjoin using every? and disjoin using some,
disjoin returns nil and disjoin returns false in cases when the
conditions fail.

Is that a good idea? Does renaming disjoin to disjoin? make any sense?

Regards,
BG

--
Baishampayan Ghose
b.ghose at gmail.com

Justin Balthrop

unread,
Jan 24, 2011, 11:00:49 AM1/24/11
to cloju...@googlegroups.com, Clojure Dev
I have similar functions named 'any' and 'all' in my utils library. I think having them in core makes sense.

Both return functions, so it doesn't make sense for disjoin/any to end in ?

> --
> You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
> To post to this group, send email to cloju...@googlegroups.com.
> To unsubscribe from this group, send email to clojure-dev...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/clojure-dev?hl=en.
>

Christophe Grand

unread,
Jan 24, 2011, 11:45:11 AM1/24/11
to cloju...@googlegroups.com
Hi,

I'm not a huge fan of varargs here since in most code where I needed this kind of functinality I already had collections.

As a side note, you can simplify this kind of code by inverting args and preds walks:
(defn conjoin [& preds]
  (fn [& args] (every? #(every? % args) preds)))

(defn disjoin [& preds]
  (fn [& args] (some #(some % args) preds)))

Christophe
--
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.cgrand.net/ (en)

Sean Devlin

unread,
Jan 24, 2011, 12:23:44 PM1/24/11
to cloju...@googlegroups.com
I have a version very similar to Christophe's code in my libs.  +1 for core.

Fogus

unread,
Jan 24, 2011, 12:19:35 PM1/24/11
to Clojure Dev
> As a side note, you can simplify this kind of code by inverting args and
> preds walks

Thank you. I should have had to look over my work before
posting. :-)

Alan

unread,
Jan 24, 2011, 1:29:37 PM1/24/11
to Clojure Dev
Seconded. I was actually about to put a request for these on JIRA when
I found Fogus's request here.

On Jan 24, 8:00 am, Justin Balthrop <jus...@justinbalthrop.com> wrote:
> I have similar functions named 'any' and 'all' in my utils library. I think having them in core makes sense.
>
> Both return functions, so it doesn't make sense for disjoin/any to end in ?
>
> > [1]: Nicer formatting and examples athttps://gist.github.com/790187

Tom Faulhaber

unread,
Jan 24, 2011, 5:17:21 PM1/24/11
to cloju...@googlegroups.com
I'll chime in here as well: I've been using conjoin a lot in some code I've been doing to analyze bug databases.

So: +1

Steve Miner

unread,
Jan 24, 2011, 6:31:08 PM1/24/11
to cloju...@googlegroups.com
I like Christophe's implementations. I agree that the proposed functions would be useful. It's probably good to spend a release cycle in contrib. You could start a higher-order functions section for contrib. As an aside, I think it's important that we keep new users in mind when adding functions to core. Lots of useful functions are outside of core (such as the set functions), and I don't feel that the proposed methods need to be in core right away.

I'm concerned about the proposed names being confused with conj and disj (especially by new users.) In particular, the doc strings say that they're short for conj[oin] and disj[oin]. 'any' and 'all' might be better. Although, confusion with 'any?' could also be an issue. That's another reason to go with contrib for the first release.

Clojure already has comp and juxt, which follow this pattern of taking var-args of functions. That part seems OK to me.

Regards,
Steve Miner

Laurent PETIT

unread,
Jan 24, 2011, 6:36:25 PM1/24/11
to cloju...@googlegroups.com
If the final target would be clojure.core, then clojure.contrib.core
would be an ideal candidate ?

2011/1/25 Steve Miner <steve...@gmail.com>:

Sean Devlin

unread,
Jan 24, 2011, 6:41:56 PM1/24/11
to cloju...@googlegroups.com
I named my versions any-pred & every-pred, fwiw.

Cosmin Stejerean

unread,
Jan 24, 2011, 9:02:50 PM1/24/11
to cloju...@googlegroups.com
On Mon, Jan 24, 2011 at 5:41 PM, Sean Devlin <francoi...@gmail.com> wrote:
I named my versions any-pred & every-pred, fwiw.

+1 for any-pred and every-pred instead of conjoin and disjoin.


--
Cosmin Stejerean
http://offbytwo.com

Alex Miller

unread,
Jan 24, 2011, 10:52:58 PM1/24/11
to cloju...@googlegroups.com
I needed these just last week!  +1

I concur in disliking conjoin and disjoin although I don't have a strong preference for any of the alternatives mentioned.  any and all/every seem like better words.  


From: Cosmin Stejerean <cos...@offbytwo.com>
To: cloju...@googlegroups.com
Sent: Mon, January 24, 2011 8:02:50 PM
Subject: Re: conjoin and disjoin for core or contrib?

Robert McIntyre

unread,
Jan 24, 2011, 11:30:47 PM1/24/11
to cloju...@googlegroups.com
How about clojure.contrib.function-utils for a possible target in contrib?

--Robert McIntyre

Fogus

unread,
Jan 25, 2011, 8:04:28 AM1/25/11
to Clojure Dev
So it seems that there is some interest in the following:

- Contribify these functions
- ... in a new contrib module (functional, combinators, fun, other?)
- ... with different names (any/every-pred, other?)
- ... and (possibly) include other similar functions

I'm happy to spear-head setting this up if Clojure/core is interested.

Rich Hickey

unread,
Jan 26, 2011, 8:09:11 AM1/26/11
to cloju...@googlegroups.com

I'll take them in core as every-pred and any-pred, but you'll have to
do the variadic unrolling as per comp and juxt. Extra credit for a
macro that eliminates the tedium of such unrolling and works for comp,
juxt et al.

Thanks,

Rich

Stuart Halloway

unread,
Jan 28, 2011, 11:09:33 AM1/28/11
to cloju...@googlegroups.com
> --
> You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
> To post to this group, send email to cloju...@googlegroups.com.
> To unsubscribe from this group, send email to clojure-dev...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/clojure-dev?hl=en.
>

Thanks for the work on this, Fogus! The patch needs a small fix, and maybe some discussion about the name "some" vs. "any". I would like to get this in today, if anybody has time to respond to questions at http://dev.clojure.org/jira/browse/CLJ-729.

Stu

Stuart Halloway
Clojure/core
http://clojure.com


Sean Devlin

unread,
Jan 28, 2011, 12:29:10 PM1/28/11
to cloju...@googlegroups.com
I agree with you comments about the boolean behavior of every-pred. 

I've also deliberately named my version of any-pred that way, because it return a boolean.  Of course, I also think there should be a any? fn in core as well, so YMMV.

I'd add one more expression to each fn, like so

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

(defn any-pred [& preds]
(fn [& args] (if (some #(some % args) preds)) true false))
My $.02

Sean

Paul Stadig

unread,
Jan 28, 2011, 2:16:41 PM1/28/11
to cloju...@googlegroups.com
Perhaps it all depends upon your application, but the original version is better for lazy seqs. With Christophe's version this will never return

(apply (conjoin pos? even?) (iterate inc 1))


Paul

Sean Devlin

unread,
Jan 28, 2011, 2:25:22 PM1/28/11
to cloju...@googlegroups.com
Yeah, that's an "oops"  Chistophe + Binary return is what I meant.

Benjamin Teuber

unread,
Feb 5, 2011, 5:06:11 AM2/5/11
to Clojure Dev
Also needed these function this week - but I called them and? and or?.
Not sure if it's best to use ? as suffix for higher-order predicates,
but I've added a bunch more and it seems quite readable to me:

((and? sequential?
(first? odd?)
(second? (=? 42)))
[5 42])

=> true

Alan

unread,
Feb 7, 2011, 12:42:20 PM2/7/11
to Clojure Dev
I don't see the value in your additional predicates, and they're not
super-easy to read, either. Given that and? exists, I would write the
below as:

((and? sequential?
(comp odd? first)
(comp #{42} second)
[5 42])
Reply all
Reply to author
Forward
0 new messages