For a long time, people have been suggesting that various libraries be
promoted from contrib into clojure core. Last week, we started making
some of the necessary code changes.
==== THE PROBLEM ====
While the changes to Clojure itself are only additive and non-
breaking, they can nevertheless cause breakages in your code:
(1) If you defined your own function 'foo', and Clojure gets a new
core function named 'foo', your definition would cause an error.
(2) Third party libs can create situation #1 behind your back. In
fact, this situation is almost guaranteed to occur when promoting
functions from contrib! If clojure.contrib.seq/group-by goes into
core, then people who were using the contrib version could get an error.
I (and other library authors) spent some time and effort to adapt to
these changes, but it is a PITA. It has already caused cascading
breakage in circumspec, labrepl, leiningen, swank, and incanter (to
name a few).
One solution would be consensus around, and rigorous correct use of,
an elegant dependency management tool. Since that ain't likely, here's
another possibility:
==== A SIMPLER SOLUTION: WARN, DON'T ERR ====
So Rich has given us something else: as of yesterday's commit
ab9a567faecc8cfde4625654fe9bb92988d7494d, attempting to define or
refer a var that is already referred from another namespace causes a
*warning*, not an *error*. So, for the example of 'group-by' being
moved into core, you might see the following warning message when
using a library that isn't updated yet:
WARNING: group-by already refers to: #'clojure.core/group-by in
namespace: incanter.core, being replaced by: #'incanter.core/group-by
That's a lot better than being dead with an error.
==== GETTING RID OF THOSE WARNINGS ====
In this case, the warning is innocuous: Incanter uses the (now
deprecated) contrib group-by, and doesn't get the new one added to
clojure.core. Library authors can then either
(1) Update their code to use the new things core gives them. If they
defined the function themselves, just remove the definition. If they
referred in a third-party implementation, simply removed the use/
require/refer.
(2) Continue to use their own implementation of the name. This
requires *adding* an exclude, e.g. (:refer-clojure :exclude [group-by])
==== PROMOTION AND DEPRECATION ====
With "warn on name collision" in place, the sane way to promote from
one library to another is to copy the vars into their new home, but to
also leave the old ones in place (for a while). The old vars can be
marked with {:deprecated "
some.version.no"}, and old clients can
continue to use them.
So, this morning (commit 95dddbbdd748b0cc6d9c8486b8388836e6418848), I
put the promoted seq fns back into contrib as well. The result of this
should be that old code will work (with warnings telling you which
libs need updates) instead of stopping dead (with an error).
==== THIS AIN"T SET IN STONE! ====
We are testing this approach out. If it causes unforeseen foulups, we
can always go back to the old way.
But I for one think it is awesome. It is more consistent with
Clojure's dynamic approach in general. Not only does it make upgrades
less painful, it also makes it easier to try things out at the REPL.
No more "you can't def that cause somebody else did already." Now life
at the REPL is "Do what I told you, period."
I hope you will like this idea and encourage Rich to make it permanent.
Stu
--
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