matchure becoming clojure.contrib.match

40 views
Skip to first unread message

Drew Colthorp

unread,
May 23, 2010, 11:41:46 PM5/23/10
to Clojure
A few weeks ago I announced a pattern matching library called
matchure. I'm excited to say it's being merged into clojure.contrib as
clojure.contrib.match. I'd like some feedback on ideas for some
backward-incompatible changes I'm planning to make before it's
actually pushed to clojure.contrib.

In the discussion below, I'll use "matchure" when I'm speaking of the
current behavior, and "clojure.contrib.match" when I'm describing
proposed behavior of the library when it's merged in. See
http://github.com/dcolthorp/matchure/blob/master/README.md for an
introduction to matchure and the existing syntax, though I'll describe
the relevant before and after behaviors below.

Change 1: {:foo #"bar"} becomes {#"bar" :foo}

In matchure, maps test against the values of corresponding keys. I'm
going to change this so that the pattern is first and the key
second. This makes the behavior closer to let, makes
clojure.contrib.match more consistent in that patterns will always be
to the left of the matched value, and patterns like {even? :foo} read
better. This seems like an easy decision.

Change 2: Drop the question mark

In matchure, the question mark was meant to represent the matched
value. ? could act as a wildcard, ?foo acted as a wildcard that had
the side effect of storing the matched value in the variable foo, and
(odd? ?) tested the matched value for oddness. Though this can be
remembered easily (by me, at least), it doesn't fit in very well in
clojure, and I was thinking about giving each of those actions a
separate, more idiomatic representation. The new behavior would see _
as the only supported wildcard, simple symbols ("foo", not
"java.lang.String") bind variables always, and % would represent
the matched value in a list/function call pattern.

These changes together have a lot of nice interations. The
pattern-matching facility gets a lot closer to an extension of let:
for example, (let [{a :a} {:a 1}] a) and (if-match [{a :a} {:a 1}] a)
would do exactly the same thing (you'd use if-match if the matched
value may not meet all of the requirements). Function call forms will
share the same syntax as post-conditions. Pattern matching functions
become a lot more natural. For example, fib could be written

(fn-match this
([0] 1)
([1] 1)
([n] (+ (this (- n 1)) (this (- n 2)))))"

There are a few potential usability issues:

* it's easier to accidentally rebind a variable without performing a
test (which you may not realize until latert)
* you wouldn't be able to use list patterns inside #() functions
because of the overload of %
* unless other changes are made, you could accidentally rebind a class
name when you mean to do an instanceof test

My sense is that these shortcomings don't outweight the benefits
listed above. Does anyone else feel differently?

Also, binding variables by default means there needs to be a way of
specifying that a variable should act as a test value not as a
variable to be bound. I was thinking ~ (unquote) would serve this
purpose, so that (if-match [~foo x] true false) would test that (= foo
x)
and (if-match [foo x] foo) would always return x. This seems
natural to me, in that you're asking to match against the runtime
value of x instead of treating it as a static part of the pattern,
just like when using unquote in quasiquoted forms. (unquote x) would
work if you wanted to generate a matching form with a quasiquote.

Anyone have an opinion?

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

Heinz N. Gies

unread,
May 24, 2010, 8:06:45 AM5/24/10
to clo...@googlegroups.com

On May 24, 2010, at 5:41 , Drew Colthorp wrote:

> A few weeks ago I announced a pattern matching library called
> matchure. I'm excited to say it's being merged into clojure.contrib as
> clojure.contrib.match. I'd like some feedback on ideas for some
> backward-incompatible changes I'm planning to make before it's
> actually pushed to clojure.contrib.
>
> In the discussion below, I'll use "matchure" when I'm speaking of the
> current behavior, and "clojure.contrib.match" when I'm describing
> proposed behavior of the library when it's merged in. See
> http://github.com/dcolthorp/matchure/blob/master/README.md for an
> introduction to matchure and the existing syntax, though I'll describe
> the relevant before and after behaviors below.

Reading the manual it looks awesome even so I hadn't had the chance to use it yet! Nice work :)

Regards,
Heinz

Antony Blakey

unread,
May 24, 2010, 8:18:00 PM5/24/10
to clo...@googlegroups.com

On 24/05/2010, at 1:11 PM, Drew Colthorp wrote:

> A few weeks ago I announced a pattern matching library called
> matchure. I'm excited to say it's being merged into clojure.contrib as
> clojure.contrib.match. I'd like some feedback on ideas for some
> backward-incompatible changes I'm planning to make before it's
> actually pushed to clojure.contrib.

...

> Anyone have an opinion?

Yes - please don't put this in clojure.contrib, for two reasons:

1. The stated instruction is to not depend on clojure.contrib, and the feedback I've received when I stated that I did in fact depend on it was that I was a fool for not following the instructions i.e. RTFI.

2. clojure.contrib is a large, monolithic bag of stuff, with a single version number. So to track changes to matchure I will be forced to track all of the changes to clojure.contrib. This is made even more difficult because clojure.contrib has no backwards compatibility intention. I know you don't either, but given the large number of different components in clojure.contrib, the likelihood of breaking changes for each commit is greatly increased. It's been breaking a lot recently, and given the number of third party components that depend on it (in spite of the warning), the knock-on effect is playing havoc with configuration management.

Why don't you just keep developing as matchure - there's no reason that everything destined for core needs to first pass into the quarantine zone that is clojure.contrib.

Antony Blakey
--------------------------
CTO, Linkuistics Pty Ltd
Ph: 0438 840 787

I contend that we are both atheists. I just believe in one fewer god than you do. When you understand why you dismiss all the other possible gods, you will understand why I dismiss yours.
--Stephen F Roberts

Stuart Halloway

unread,
May 24, 2010, 8:33:53 PM5/24/10
to clo...@googlegroups.com
Contrib (the license, provenance assurance, issue tracking) is one
thing. Contrib (the monolithic deployment jar) is another.

Historically they have been the same, but they don't have to be.
Antony wants simple minimal dependencies. I want the provenance
assurance, and the process that is (slowly) coming into play with
Contrib.

How can we get both?

Stu

Phil Hagelberg

unread,
May 24, 2010, 9:07:21 PM5/24/10
to clo...@googlegroups.com
On Mon, May 24, 2010 at 2:33 PM, Stuart Halloway
<stuart....@gmail.com> wrote:
> Contrib (the license, provenance assurance, issue tracking) is one thing.
> Contrib (the monolithic deployment jar) is another.
>
> Historically they have been the same, but they don't have to be. Antony
> wants simple minimal dependencies. I want the provenance assurance, and the
> process that is (slowly) coming into play with Contrib.

I strongly support not putting any new libraries into contrib until
this is resolved. Forcing every lib in contrib to have the same
version number causes a lot of nasty constraints with regards to
release cycles and breaking changes.

-Phil

Meikel Brandmeyer

unread,
May 25, 2010, 1:40:37 AM5/25/10
to Clojure
Hi,

On May 25, 2:33 am, Stuart Halloway <stuart.hallo...@gmail.com> wrote:

> How can we get both?

By providing a non-monolithic build? Once upon a time, I did
this in a non-intrusive way using Ivy[1]. Back then the interest
was close to zero. Now that contrib uses maven, this should be
a non-brainer, no? Create a subproject for each logical module.
People can depend on fine-grained modules. The modules may
(but don't have to) do releases independently from each other.

Sincerely
Meikel

[1]: http://github.com/kotarak/clojure-contrib/tree/ivy-dependency-management
and in particular:
http://github.com/kotarak/clojure-contrib/blob/ivy-dependency-management/gen-modules.clj

Antony Blakey

unread,
May 25, 2010, 1:57:58 AM5/25/10
to clo...@googlegroups.com

On 25/05/2010, at 3:10 PM, Meikel Brandmeyer wrote:

> Hi,
>
> On May 25, 2:33 am, Stuart Halloway <stuart.hallo...@gmail.com> wrote:
>
>> How can we get both?
>
> By providing a non-monolithic build?

Yes, and ensuring that the subprojects use semantic versioning e.g. major version number increments on a non-backwards compatible change, and hopefully real subproject releases that one can depend on. Something doesn't have to be perfect before it's usable, so people should be encouraged to do real releases as opposed to forever staying in alpha/beta and hence never providing reliable semantic versioning drop points e.g. stable major version numbers. I only raise this point because being a subproject IME discourages major-point releases in deference to the version number of the containing project.

In an ideal world of course.

Antony Blakey
--------------------------
CTO, Linkuistics Pty Ltd
Ph: 0438 840 787

Reflecting on W.H. Auden's contemplation of 'necessary murders' in the Spanish Civil War, George Orwell wrote that such amorality was only really possible, 'if you are the kind of person who is always somewhere else when the trigger is pulled'.
-- John Birmingham, "Appeasing Jakarta"

B Smith-Mannschott

unread,
May 25, 2010, 7:16:32 AM5/25/10
to clo...@googlegroups.com
On Mon, May 24, 2010 at 05:41, Drew Colthorp <dcol...@gmail.com> wrote:
> A few weeks ago I announced a pattern matching library called
> matchure. I'm excited to say it's being merged into clojure.contrib as
> clojure.contrib.match. I'd like some feedback on ideas for some
> backward-incompatible changes I'm planning to make before it's
> actually pushed to clojure.contrib.
>
> In the discussion below, I'll use "matchure" when I'm speaking of the
> current behavior, and "clojure.contrib.match" when I'm describing
> proposed behavior of the library when it's merged in. See
> http://github.com/dcolthorp/matchure/blob/master/README.md for an
> introduction to matchure and the existing syntax, though I'll describe
> the relevant before and after behaviors below.
>
> Change 1: {:foo #"bar"} becomes {#"bar" :foo}
>
> In matchure, maps test against the values of corresponding keys. I'm
> going to change this so that the pattern is first and the key
> second. This makes the behavior closer to let, makes
> clojure.contrib.match more consistent in that patterns will always be
> to the left of the matched value, and patterns like {even? :foo} read
> better. This seems like an easy decision.

This strikes me as an odd change. Did you overlook the fact that map
keys have to be unique?

{even? :foo,
even? :bar}

Might read nicely, but will it work?

// Ben

Jason Smith

unread,
May 25, 2010, 2:59:44 PM5/25/10
to Clojure
I agree with Meikel on this one. Java isn't the best language, but
they figured out how to package code in a way that makes it easy to
reuse - the JAR. Maven may not be the easiest thing in the world to
work with, but they got dependency management right.

clojure-contrib should probably be broken up eventually. Some pieces
could arguably be brought into core. Other pieces are obviously half-
baked (I won't name names) and should be pulled into separate projects
so that they can be dynamic and alive, rather than a slave to a
monolithic release cycle.

It would be nice to have a single place you could go to find/search
Clojure libraries... that way you don't rely on clojure-contrib to be
the *only* source of reusable Clojure code in the known
universe. :-) Oh, hey, what about http://clojure.org/libraries ?

Drew Colthorp

unread,
May 26, 2010, 1:40:13 PM5/26/10
to Clojure
Good point Ben. That change was obviously ill-conceived.

On May 25, 7:16 am, B Smith-Mannschott <bsmith.o...@gmail.com> wrote:


> On Mon, May 24, 2010 at 05:41, Drew Colthorp <dcolth...@gmail.com> wrote:
> > A few weeks ago I announced a pattern matching library called
> >matchure. I'm excited to say it's being merged into clojure.contrib as
> > clojure.contrib.match. I'd like some feedback on ideas for some
> > backward-incompatible changes I'm planning to make before it's
> > actually pushed to clojure.contrib.
>
> > In the discussion below, I'll use "matchure" when I'm speaking of the
> > current behavior, and "clojure.contrib.match" when I'm describing
> > proposed behavior of the library when it's merged in. See
> >http://github.com/dcolthorp/matchure/blob/master/README.mdfor an

> > introduction tomatchureand the existing syntax, though I'll describe


> > the relevant before and after behaviors below.
>
> > Change 1: {:foo #"bar"} becomes {#"bar" :foo}
>

> > Inmatchure, maps test against the values of corresponding keys. I'm

Reply all
Reply to author
Forward
0 new messages