The intent of making it a macro is that it allows short-circuit evaluation,
like Clojure's or/and.  There is no reason to evaluate comparisons between
keys when an earlier comparison has already decided the ordering.

Hardwiring in the compare function and the order between %1 and %2 is an
interesting idea I hadn't considered, partly because it is often the case
that one would like an ascending sort order on one key, but descending on
others, which is commonly done by swapping %1 and %2's position, but could
also be done by negating the return value of compare.

Andy

On Wed, Dec 7, 2011 at 6:59 PM, Alan Malloy <[email protected]> wrote:

> This should be a function, not a macro. In fact it is just:
>
> (defn multicmp [& xs] (first (remove zero? xs)))
>
> But what you really wanted to begin with is a comparator function, so
> more like:
>
> (defn multicmp [& keys]
>  (fn [a b]
>    (or (first (remove zero? (map #(compare (% a) (% b))
>                                  keys)))
>        0)))
>
> (sort-by (multicmp < =) coll)
>
> On Dec 7, 5:51 pm, Andy Fingerhut <[email protected]> wrote:
> > I've been going through the PLEAC web site, writing Clojure examples
> > corresponding to the Perl code examples from the Perl Cookbook:
> >
> > http://pleac.sourceforge.net
> >
> > Michael Bacarella started a github repo to collect these together, and
> I'm
> > helping flesh some of them out.
> >
> > https://github.com/mbacarella/pleac-clojure
> >
> > One thing that is very convenient in Perl is doing sorts on multiple
> > comparison keys -- since 0 is treated as logically false in Perl, they
> can
> > simply do what in Clojure would look like:
> >
> > (sort #(or (compare (key1 %1) (key2 %2))
> >                 (compare (key2 %1) (key2 %2))
> >                 ...)
> >          collection)
> >
> > This doesn't work in Clojure, because it only treats nil or false as
> > logically false.  It is easy to write a short-circuiting macro 'multicmp'
> > that does the correct thing:
> >
> > (defmacro multicmp
> >   ([x] x)
> >   ([x & next]
> >      `(let [cmp# ~x]
> >         (if (not= cmp# 0)
> >           cmp#
> >           (multicmp ~@next)))))
> >
> > Then just replace 'or' in the first code snippet with 'multicmp'.
> >
> > Does something like this already exist in a library I'm unaware of?
>  Would
> > others find it useful to have around?  And any suggestions on where it
> best
> > belongs if so?
> >
> > Thanks,
> > Andy
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to