ANN: Clojure 1.5

8,521 views
Skip to first unread message

Stuart Halloway

unread,
Mar 1, 2013, 10:56:58 AM3/1/13
to clo...@googlegroups.com, cloju...@googlegroups.com
We are pleased to announce the release of Clojure 1.5.

Getting Clojure:

  Web:              http://clojure.org/downloads
  Lein/Maven:   :dependencies [[org.clojure/clojure "1.5.0"]]

Note that it will take a few hours for the links above to become live,
as the completed build moves into Maven Central.

This release includes significant features and bug fixes, documented
here:


The number of Clojure contributors continues to grow. Thanks to all
the people whose code is included in this release:

Aaron Bedra 
Alan Malloy
Alex Redington  
Alf Kristian Stoyle 
Ambrose Bonnaire-Sergeant 
Andy Fingerhut 
Brandon Bloom 
Brenton Ashworth 
Bronsa 
Chas Emerick 
Christophe Grand 
Colin Jones 
Cosmin Stejerean 
Daniel Solano Gómez 
David Powell 
David Santiago 
Ed Bowler 
Federico Brubacher 
Gabriel Horner 
Gary Fredericks 
Herwig Hochleitner 
Hubert Iwaniuk 
Hugo Duncan 
John Szakmeister 
Juha Arpiainen 
Justin Kramer 
Kevin Downey 
Laurent Petit 
Meikel Brandmeyer 
Michael Fogus
Michał Marczyk 
Michel Alexandre Salim 
Philip Aston 
Philip Potter 
Rich Hickey 
Scott Lowe 
Steve Miner 
Stuart Halloway 
Stuart Sierra 
Tassilo Horn 
Toby Crawley 
Tom Faulhaber 

Thanks to all involved!

Stu Halloway
Clojure/core



Tassilo Horn

unread,
Mar 1, 2013, 11:46:50 AM3/1/13
to Stuart Halloway, clo...@googlegroups.com, cloju...@googlegroups.com
Stuart Halloway <stuart....@gmail.com> writes:

Hi Stu,

> We are pleased to announce the release of Clojure 1.5.

Great, except that if I change my project's dependency from 1.5.0-RC17
to 1.5.0, I get this error when trying to "lein test". With RC17, it
works just fine.

--8<---------------cut here---------------start------------->8---
% lein test
Exception in thread "main" java.lang.RuntimeException: java.io.FileNotFoundException: Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath:
at clojure.lang.Util.runtimeException(Util.java:165)
at clojure.lang.Compiler.eval(Compiler.java:6476)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.load(Compiler.java:6902)
at clojure.lang.RT.loadResourceScript(RT.java:357)
at clojure.lang.RT.loadResourceScript(RT.java:348)
at clojure.lang.RT.load(RT.java:427)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:604)
at clojure.core$use.doInvoke(core.clj:5363)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at funnyqt.emf$eval154$loading__4505__auto____155.invoke(emf.clj:1)
at funnyqt.emf$eval154.invoke(emf.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.load(Compiler.java:6902)
at clojure.lang.RT.loadResourceScript(RT.java:357)
at clojure.lang.RT.loadResourceScript(RT.java:348)
at clojure.lang.RT.load(RT.java:427)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$require.doInvoke(core.clj:5352)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at funnyqt.declarative_test$eval148$loading__4505__auto____149.invoke(declarative_test.clj:1)
at funnyqt.declarative_test$eval148.invoke(declarative_test.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.load(Compiler.java:6902)
at clojure.lang.RT.loadResourceScript(RT.java:357)
at clojure.lang.RT.loadResourceScript(RT.java:348)
at clojure.lang.RT.load(RT.java:427)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$require.doInvoke(core.clj:5352)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:602)
at user$eval75.invoke(NO_SOURCE_FILE:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
at clojure.lang.Compiler.eval(Compiler.java:6455)
at clojure.lang.Compiler.eval(Compiler.java:6431)
at clojure.core$eval.invoke(core.clj:2795)
at clojure.main$eval_opt.invoke(main.clj:296)
at clojure.main$initialize.invoke(main.clj:315)
at clojure.main$null_opt.invoke(main.clj:348)
at clojure.main$main.doInvoke(main.clj:426)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:405)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:518)
at clojure.main.main(main.java:37)
Caused by: java.io.FileNotFoundException: Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath:
at clojure.lang.RT.load(RT.java:430)
at clojure.lang.RT.load(RT.java:398)
at clojure.core$load$fn__4610.invoke(core.clj:5386)
at clojure.core$load.doInvoke(core.clj:5385)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5200)
at clojure.core$load_lib.doInvoke(core.clj:5237)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$load_libs.doInvoke(core.clj:5271)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:602)
at clojure.core$require.doInvoke(core.clj:5352)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at funnyqt.query$eval1177$loading__4505__auto____1178.invoke(query.clj:1)
at funnyqt.query$eval1177.invoke(query.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6465)
... 75 more
Tests failed.
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo

David Powell

unread,
Mar 1, 2013, 12:41:04 PM3/1/13
to cloju...@googlegroups.com, Stuart Halloway, clo...@googlegroups.com
works for me... do you have some sort of version conflict perhaps?

user=> (clojure-version)
"1.5.0"
user=> (require '[clojure.core.reducers :as r])
nil
user=> (r/fold + (range 1000))
499500




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



Tassilo Horn

unread,
Mar 1, 2013, 1:30:15 PM3/1/13
to David Powell, cloju...@googlegroups.com, Stuart Halloway, clo...@googlegroups.com
David Powell <djpo...@djpowell.net> writes:

Hi David,

> works for me... do you have some sort of version conflict perhaps?

Indeed, you are right. With dependency [org.clojure/clojure "1.5.0"],
my project's actually started with clojure 1.4.0. With
[org.clojure/clojure "1.5.0-RC17"], it's started with exactly that.

Uhm, why is that? My complete dependencies are:

:dependencies [[org.clojure/clojure "1.5.0"]
[de.uni-koblenz.ist/jgralab "7.4.4"] ;; no deps in pom.xml
[org.clojure/core.logic "0.8.0-rc2"] ;; no deps in pom.xml
[ordered "1.3.2"] ;; dep on clj 1.4.0
[org.clojure/tools.macro "0.1.2"] ;; no deps in pom.xml
[emf-xsd-sdk "2.8.0"]] ;; no deps in pom.xml

Interestingly, when I comment the dependency [ordered "1.3.2"] and do
"lein repl", I get clojure *1.3.0*!?!

So to summarize:

clj 1.5.0-RC17 + ordered 1.3.2 => clj 1.5.0-RC17 is used
clj 1.5.0 + ordered 1.3.2 => clj 1.4.0 is used
clj 1.5.0 no ordered 1.3.2 => clj 1.3.0 is used

Can anymone make sense of that?

Bye,
Tassilo

Tassilo Horn

unread,
Mar 1, 2013, 1:45:29 PM3/1/13
to Joey Ezechiëls, clo...@googlegroups.com, Stuart Halloway, cloju...@googlegroups.com
Joey Ezechiëls <jeanp...@gmail.com> writes:

Hi Joey,

> Hi Tassilo, are you using java v1.6? because according to the
> changelog, reducers need an extra lib to work on java 1.6, while 1.7
> should be fine as-is.

No, I use 1.7. The problem is that actually clojure 1.4.0 gets started
although my dependencies say I want 1.5.0. See my other mail:

Message-ID: <87lia7a...@thinkpad.tsdh.de>

Bye,
Tassilo

J.J. Ezechiëls

unread,
Mar 1, 2013, 1:50:15 PM3/1/13
to Joey Ezechiëls, clo...@googlegroups.com, Stuart Halloway, cloju...@googlegroups.com
Are you using any special libs? I just tried to reproduce your problem by upgrading a relatively simple project to clojure 1.5 and got no problems.

Best regards,
Joey Ezechiëls

Michael Klishin

unread,
Mar 1, 2013, 2:02:42 PM3/1/13
to clo...@googlegroups.com

2013/3/1 Tassilo Horn <ts...@gnu.org>

So to summarize:

  clj 1.5.0-RC17 + ordered 1.3.2 => clj 1.5.0-RC17 is used
  clj 1.5.0      + ordered 1.3.2 => clj 1.4.0 is used
  clj 1.5.0     no ordered 1.3.2 => clj 1.3.0 is used

Can anymone make sense of that?

This reminds me of

Maybe we can start another thread for this issue, though?
Doesn't seem to be Clojure 1.5's fault.
--
MK

http://github.com/michaelklishin
http://twitter.com/michaelklishin

Tassilo Horn

unread,
Mar 1, 2013, 2:24:10 PM3/1/13
to Michael Klishin, clo...@googlegroups.com
Michael Klishin <michael....@gmail.com> writes:

> 2013/3/1 Tassilo Horn <ts...@gnu.org>
>
>> So to summarize:
>>
>> clj 1.5.0-RC17 + ordered 1.3.2 => clj 1.5.0-RC17 is used
>> clj 1.5.0 + ordered 1.3.2 => clj 1.4.0 is used
>> clj 1.5.0 no ordered 1.3.2 => clj 1.3.0 is used
>>
>> Can anymone make sense of that?
>
> This reminds me of
> https://github.com/technomancy/leiningen/issues/1035

Yes, this sounds very similar. And the report also contains a fix: just
put

:exclusions [org.clojure/clojure]

in every dependency that defines its own clojure dependency.

> Maybe we can start another thread for this issue, though?
> Doesn't seem to be Clojure 1.5's fault.

Indeed. If anybody is interested in playing around with this issue,
here's a cut-down version of my project.clj to reproduce it.

--8<---------------cut here---------------start------------->8---
(defproject foo "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.5.0"]
[org.clojure/core.logic "0.8.0-rc2"]
[ordered "1.3.2"]
[org.clojure/tools.macro "0.1.2"]]
:profiles {:dev
{:dependencies
[[criterium "0.3.1"] ;; Benchmarking
[clj-ns-browser "1.3.0"]]}})

Tassilo Horn

unread,
Mar 1, 2013, 2:45:53 PM3/1/13
to Cosmin Stejerean, cloju...@googlegroups.com, David Powell, Stuart Halloway, clojure
Cosmin Stejerean <cos...@offbytwo.com> writes:

> core.logic might not have any dependencies in its pom, but the parent
> pom (pom.contrib) does depend on clojure 1.3.0 by default.

Aha, there are parent poms. I didn't know that. Are there also aunt
and uncle poms? (I love maven so much!) ;-)

Anyway, I could workaround the issue by specifying all my deps like

[dep "version" :exclusions [org.clojure/clojure]]

Bye,
Tassilo

Rich Morin

unread,
Mar 1, 2013, 2:55:03 PM3/1/13
to clo...@googlegroups.com
On Mar 1, 2013, at 07:56, Stuart Halloway wrote:
> The number of Clojure contributors continues to grow. Thanks to all
> the people whose code is included in this release:
>
> Aaron Bedra
> ...
>
> Thanks to all involved!

I think that it would be appropriate (and possibly spur participation)
to give specific credit to anyone who has submitted useful bug reports,
enhancement requests, etc.

-r

--
http://www.cfcl.com/rdm Rich Morin
http://www.cfcl.com/rdm/resume r...@cfcl.com
http://www.cfcl.com/rdm/weblog +1 650-873-7841

Software system design, development, and documentation


Nelson Morris

unread,
Mar 1, 2013, 5:02:50 PM3/1/13
to clo...@googlegroups.com, Michael Klishin
> --
> --
> 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
> ---
> You received this message because you are subscribed to the Google Groups "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

The chain causing problems for you is:

[clj-ns-browser "1.3.0"] -> [seesaw "1.4.2"] -> [j18n "1.0.1"] ->
[org.clojure/clojure "[1.2,1.5)"]

The last one there allows clojure below 1.5, which includes -RC17. As
soon as you bump to to 1.5 it ignores the "soft" version in your
:dependencies, and chooses one in the range based on your other
dependencies.

You should just need the :exclusion in clj-ns-browser.

-
Nelson Morris

Alex Baranosky

unread,
Mar 2, 2013, 1:15:39 AM3/2/13
to clo...@googlegroups.com, cloju...@googlegroups.com
Congratulations on the new release.  Thanks for all your hard work.

On Fri, Mar 1, 2013 at 5:08 PM, Jean Baro <jfb...@gmail.com> wrote:
Congratulations for every one involved in making clojure the most fun to work language there is.
--
--
You received this message because you are subscribed to the Google

Tassilo Horn

unread,
Mar 2, 2013, 5:26:47 AM3/2/13
to Nelson Morris, clo...@googlegroups.com, Michael Klishin
Nelson Morris <nmo...@nelsonmorris.net> writes:

Hi Nelson,

> The chain causing problems for you is:
>
> [clj-ns-browser "1.3.0"] -> [seesaw "1.4.2"] -> [j18n "1.0.1"] ->
> [org.clojure/clojure "[1.2,1.5)"]
>
> The last one there allows clojure below 1.5, which includes -RC17. As
> soon as you bump to to 1.5 it ignores the "soft" version in your
> :dependencies, and chooses one in the range based on your other
> dependencies.

Ah, ok, so that's why clj 1.5.0 is out. And when it has freedom to
choose between a range of versions, it chooses the oldest one?

That would explain why it selects 1.4.0 when I have ordered 1.3.2 as
dependency which itself requires clj 1.4.0, and why I get clj 1.3.0 if I
take out the dependency on ordered 1.3.2.

Bye,
Tassilo

Frank Siebenlist

unread,
Mar 2, 2013, 5:17:30 PM3/2/13
to clo...@googlegroups.com, clo...@googlegroups.com, Michael Klishin
> ...
> The chain causing problems for you is:
>
> [clj-ns-browser "1.3.0"] -> [seesaw "1.4.2"] -> [j18n "1.0.1"] ->
> [org.clojure/clojure "[1.2,1.5)"]
>
> The last one there allows clojure below 1.5, which includes -RC17. As
> soon as you bump to to 1.5 it ignores the "soft" version in your
> :dependencies, and chooses one in the range based on your other
> dependencies.
>
> You should just need the :exclusion in clj-ns-browser.
>
> -
> Nelson Morris

As i'm responsible for the clj-ns-browser release...
And although the dependency issue seems another 2 levels down, can i specify anything differently in my project file to prevent this?

Or is this a bug in leiningen's dependency resolution?

Or both...

Regards, Frank.

Dave Ray

unread,
Mar 2, 2013, 5:25:05 PM3/2/13
to clo...@googlegroups.com
I'll push a new release of seesaw this weekend to isolate the issue.
It seems like a clj-ns-browser release with the new seesaw version
would then be appropriate.

Nelson pointed this issue out to me a while ago, but 1.5 seemed so far
off at the time. Sorry about the pain.

Dave

Nelson Morris

unread,
Mar 2, 2013, 6:42:31 PM3/2/13
to clo...@googlegroups.com
On Sat, Mar 2, 2013 at 4:17 PM, Frank Siebenlist
<frank.si...@gmail.com> wrote:
>> ...
>> The chain causing problems for you is:
>>
>> [clj-ns-browser "1.3.0"] -> [seesaw "1.4.2"] -> [j18n "1.0.1"] ->
>> [org.clojure/clojure "[1.2,1.5)"]
>>
>> The last one there allows clojure below 1.5, which includes -RC17. As
>> soon as you bump to to 1.5 it ignores the "soft" version in your
>> :dependencies, and chooses one in the range based on your other
>> dependencies.
>>
>> You should just need the :exclusion in clj-ns-browser.
>>
>> -
>> Nelson Morris
>
> As i'm responsible for the clj-ns-browser release...
> And although the dependency issue seems another 2 levels down, can i specify anything differently in my project file to prevent this?

You could add the a similar exclusion for org.clojure/clojure in the
seesaw dependency declaration, but I'd just wait for the next seesaw
release which will handle it.

>
> Or is this a bug in leiningen's dependency resolution?
>

Unfortunately it's behaviour defined by maven. In order to be
compatible lein has to do the same thing.

I've written up a few things about version ranges at
http://nelsonmorris.net/2012/07/31/do-not-use-version-ranges-in-project-clj.html
and in some other mailing list threads. The confusion about what can
happen with dependencies led me to make
https://github.com/xeqi/lein-pedantic, which is helpful for some
cases. In addition, I hope to get some easier debugging for this case
into lein itself; issues at:
https://github.com/technomancy/leiningen/issues/734 and
https://github.com/cemerick/pomegranate/issues/54

Dave Ray

unread,
Mar 3, 2013, 1:57:43 AM3/3/13
to clo...@googlegroups.com
>> As i'm responsible for the clj-ns-browser release...
>> And although the dependency issue seems another 2 levels down, can i specify anything differently in my project file to prevent this?
>
> You could add the a similar exclusion for org.clojure/clojure in the
> seesaw dependency declaration, but I'd just wait for the next seesaw
> release which will handle it.

Seesaw 1.4.3 is released and addresses this issue. Release notes here:
https://github.com/daveray/seesaw/wiki/Release-Notes

Dave

Frank Siebenlist

unread,
Mar 3, 2013, 4:12:54 AM3/3/13
to clo...@googlegroups.com, Frank Siebenlist
clj-ns-browser 1.3.1 is released and addresses this issue by upgrading the project's dependencies to seesaw 1.4.3.

For docs and code, please see "https://github.com/franks42/clj-ns-browser".

Enjoy, Frank.

Tassilo Horn

unread,
Mar 4, 2013, 2:37:43 AM3/4/13
to Frank Siebenlist, clo...@googlegroups.com
Frank Siebenlist <frank.si...@gmail.com> writes:

Hi Frank,

> clj-ns-browser 1.3.1 is released and addresses this issue by upgrading
> the project's dependencies to seesaw 1.4.3.

With 1.3.1 I could remove all the :excusions again and it still picked
the right clojure version (1.5.0).

Thanks,
Tassilo

Frank Siebenlist

unread,
Mar 4, 2013, 3:53:39 AM3/4/13
to Tassilo Horn, Frank Siebenlist, clo...@googlegroups.com
Excellent - thanks for letting me know - Frank.

Wolodja Wentland

unread,
Mar 4, 2013, 7:00:31 AM3/4/13
to clo...@googlegroups.com
On Sat, Mar 02, 2013 at 17:42 -0600, Nelson Morris wrote:

> > Or is this a bug in leiningen's dependency resolution?

> Unfortunately it's behaviour defined by maven. In order to be compatible
> lein has to do the same thing.

> I've written up a few things about version ranges at
> http://nelsonmorris.net/2012/07/31/do-not-use-version-ranges-in-project-clj.html
> and in some other mailing list threads.

I would like to note that there is /nothing/ wrong with version ranges in
general and it would be very good if the Clojure tooling would actually
support proper and expressive dependency definitions. Unfortunately it does
not, which seems to be a bug in maven or in the fact that Clojure relies on
this. It is also ridiculous that RC or alpha/beta releases are treated in the
same way as actual ones.

Maybe it would be good to think about how this unfortunate behaviour can be
fixed, rather than relying on having to hardcode very specific dependencies.
(as in dependency on X.Y.Z even though the library in question provides a
stable API in all X.* releases)

I think this would have the following positive effects:

* Projects don't have to constantly monitor new releases of new libraries
and bug authors of libraries they use to do the same

* Library authors would be more concerned about providing a stable
interface for all releases that fall into a certain version span

* Packaging software and tools by downstream distributions (e.g. Debian,
Ubuntu, …), so that Clojure software can be easily used by people that
are /not/ familiar with Clojure can still easily use software written in
it, would be much easier.

* Deployment would be more predictable as people know that they target
only "stable" releases.

I know that I am coming from a different culture than the "Let's package
everything in a jar and it is good", but I believe that there is merit in
stabilizing APIs and in relying on libraries that honour this. I am also aware
that my experience with Python's "batteries included", Haskell's "platform",
C's SONAMEs or Debian's packaging system might have spoiled me, but still ...

It is up to a community to fix things that are broken in their toolset and "Do
not use version ranges" is IMHO the wrong answer.
--
Wolodja <bab...@gmail.com>

4096R/CAF14EFC
081C B7CD FF04 2BA9 94EA 36B2 8B7F 7D30 CAF1 4EFC
signature.asc

Meikel Brandmeyer (kotarak)

unread,
Mar 4, 2013, 7:36:59 AM3/4/13
to clo...@googlegroups.com
Hi,


Am Montag, 4. März 2013 13:00:31 UTC+1 schrieb Wolodja Wentland:

It is up to a community to fix things that are broken in their toolset and "Do
not use version ranges" is IMHO the wrong answer.


Huge +1.

I was about to blog in favour of version ranges. As I'm a toolmaker myself, I wanted to first spike a proof-of-concept of a saner dependency resolution library ("it can't be thaaat hard, right?" kind of run-up-a-wall-soon project). However now I will blog anyway and get to code later on.

Having detailed dependency reports with sane information as they were added lately to leiningen and gradle are a first step. A sane resolution strategy is the next. (Funnily ivy already seems to provide that...)

Meikel

Chas Emerick

unread,
Mar 4, 2013, 8:33:29 AM3/4/13
to clo...@googlegroups.com
FWIW, contributors to Pomegranate and Leiningen are working on general solutions to this sort of madness, but the use of version ranges will always be largely unwarranted, especially in published libraries.

There are a lot of reasons for this, but #1 for me is that few people understand the implications of version ranges, either downstream of their published libraries or when they are consuming a library and place a range around its resolution.  If you do, and your team does, then by all means, go hog-wild with version ranges in your in-house libraries and applications, where you can control versioning schemes, correspondences between APIs and versions, and so on.  However, none of those standards apply in the commons, so ranges like the one that provoked the problem in this case ([org.clojure/clojure "[1.2,1.5)"]) are counterproductive (i.e. there is no reason to prospectively exclude an unreleased version unless you're certain that API changes will break the library in question).  Granted, the fallback resolution of the Leiningen/Pomegranate/Aether triad fall down badly, which exacerbates the problem; again, that's being worked on, but the solution still won't help in this situation where a library blocks out e.g. 1.5.0, but a downstream user/library explicitly specifies 1.5.0.

I feel like I'm light-years OT, so I won't wade into the Ivy vs. Aether morass; suffice it to say, if there were a silver bullet — and there's not — Ivy wouldn't be it.

Cheers,

- Chas

Hugo Duncan

unread,
Mar 4, 2013, 9:00:42 AM3/4/13
to clo...@googlegroups.com
"Meikel Brandmeyer (kotarak)" <m...@kotka.de> writes:

> Hi,
>
> Am Montag, 4. März 2013 13:00:31 UTC+1 schrieb Wolodja Wentland:
>>
>> It is up to a community to fix things that are broken in their toolset and
>> "Do not use version ranges" is IMHO the wrong answer.
>>
> Huge +1.

Fixing version ranges seems like a good idea (e.g. I just ended up with
commons-logging on the classpath, I think due to clojure 1.5.0 being
released). Maven's answer to these issues seems to be "use
dependencyManagement" [1].

I still think the valid use cases of version ranges are quite limited
though. When does using version ranges make sense? Or thinking from a
lein perspective, what features does lein need to provide for specifying
dependency versions, and are version ranges the best way of expressing
these?

Hugo

[1] http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-project-dependencies.html#pom-relationships-sect-version-ranges

Meikel Brandmeyer (kotarak)

unread,
Mar 4, 2013, 9:01:13 AM3/4/13
to clo...@googlegroups.com
Hi Chas,


Am Montag, 4. März 2013 14:33:29 UTC+1 schrieb Chas Emerick:
There are a lot of reasons for this, but #1 for me is that few people understand the implications of version ranges, either downstream of their published libraries or when they are consuming a library and place a range around its resolution.  If you do, and your team does, then by all means, go hog-wild with version ranges in your in-house libraries and applications, where you can control versioning schemes, correspondences between APIs and versions, and so on.  However, none of those standards apply in the commons, so ranges like the one that provoked the problem in this case ([org.clojure/clojure "[1.2,1.5)"]) are counterproductive (i.e. there is no reason to prospectively exclude an unreleased version unless you're certain that API changes will break the library in question).  Granted, the fallback resolution of the Leiningen/Pomegranate/Aether triad fall down badly, which exacerbates the problem; again, that's being worked on, but the solution still won't help in this situation where a library blocks out e.g. 1.5.0, but a downstream user/library explicitly specifies 1.5.0.

Ok. So instead of the range I specify "[org.clojure/clojure "1.2"]". What does that mean? Now I either excluded *all* clojure versions not= 1.2 or the version number doesn't mean anything. Then we should get rid of it completely and just specify the dependency without it. (It seems there maven poms which do exactly that? o.O)

The range [1.2;1.5) means that the library was tested with 1.2 up to 1.4 and - believing in semver - their patchlevel children. 1.5 (was at that time) not released, yet. So compatibility couldn't be guaranteed. For me this is a reasonable approach. Sure. It might work with 1.5. Everyone is free to place an exclusion to help the system resolve the conflict. But you must be aware you might run into trouble.

If I follow your approach I must provide 4 branches of a library which basically consists of a single function: one branch per supported clojure version (so far). This is ridiculous. Or - as I said - we let all hope go and don't specify the version, only the dependency on the library itself.

I see we have a different basic idea of what a version range should mean. For me it's a promise that my library will work with the versions specified. If one wants to use a version outside the range, that *might* be ok, but one should be aware and pointed to that fact and the decision to do so should be explicit!

I'm probably just a pessimist, while you are an optimist.

Meikel

Michał Marczyk

unread,
Mar 4, 2013, 9:04:45 AM3/4/13
to clo...@googlegroups.com
Hi Wolodja,

It's useful to note that you can use the currently preferred fixed
version specifiers and still have your dependencies and the top-level
project depend on multiple versions of a library (the common case is
multiple versions of Clojure specified as dependencies).

Also, you can specify a baseline version requirement in project.clj
and then still specify tests for your library including alternative
version sets; that makes explicit what has been tested and what simply
"might" work.

Apart from noting the above, I have to say I simply don't see the
benefit of version ranges. Here's a bunch of comments on the list of
positive effects:

On 4 March 2013 13:00, Wolodja Wentland <bab...@gmail.com> wrote:
> I think this would have the following positive effects:
>
> * Projects don't have to constantly monitor new releases of new libraries
> and bug authors of libraries they use to do the same

That is true today in the sense that if your code works now, it will
continue to work regardless of which libraries release new versions,
as long as you don't change your :dependencies in project.clj or the
equivalent for your build tool.

On the other hand, if you care about securing your project, pulling in
the latest bugfixes etc., you will need to monitor new releases
anyway, regardless of the version numbering scheme used by their
maintainers.

> * Library authors would be more concerned about providing a stable
> interface for all releases that fall into a certain version span

Those library authors who care about this already act in this way.

> * Packaging software and tools by downstream distributions (e.g. Debian,
> Ubuntu, …), so that Clojure software can be easily used by people that
> are /not/ familiar with Clojure can still easily use software written in
> it, would be much easier.

Are people actually using package managers for Java libraries and
applications much, beyond a small number of special cases like
LibreOffice (which therefore can totally be packaged überjar-like)?

> * Deployment would be more predictable as people know that they target
> only "stable" releases.

In the absence of version ranges, that seems to be true today...?

> I know that I am coming from a different culture than the "Let's package
> everything in a jar and it is good", but I believe that there is merit in
> stabilizing APIs and in relying on libraries that honour this. I am also aware
> that my experience with Python's "batteries included", Haskell's "platform",
> C's SONAMEs or Debian's packaging system might have spoiled me, but still ...

Here's a relevant link to a post on Yesod's blog from April 2012 (one
of top Haskell web frameworks):

http://www.yesodweb.com/blog/2012/04/cabal-meta

And here's an interesting quote (again, this is from Yesod's own
blog): "Even with all these tools, one day I found myself completely
incapable of installng Yesod from source."

I know Cabal is improving and it actually has a shot at solving some
truly interesting problems with dependency handling, but right now I
find it surprising that one could feel "spoiled" by using it to the
point of feeling discomfort in Clojure land. (We actually have it
simpler for example in that we don't have to deal much with
assumptions baked into previously compiled artefacts; I'm not knocking
Cabal here in any way, just noting that it's not all that rosy.)

> It is up to a community to fix things that are broken in their toolset and "Do
> not use version ranges" is IMHO the wrong answer.

There's value in using Maven simply for the easy interop with the vast
Java ecosystem behind it. Maven's (Aether's?) handling of version
ranges appears to be counterintuitive. I'm not sure to which degree
this can be fixed on the Leiningen / Pomegranate side, but if we do
expend effort fixing that, what can we expect to get in return?

Cheers,
Michał

Wolodja Wentland

unread,
Mar 4, 2013, 9:11:27 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 04, 2013 at 08:33 -0500, Chas Emerick wrote:

> FWIW, contributors to Pomegranate and Leiningen are working on general
> solutions to this sort of madness, but the use of version ranges will always be
> largely unwarranted, especially in published libraries.

> There are a lot of reasons for this, but #1 for me is that few people
> understand the implications of version ranges, either downstream of their
> published libraries or when they are consuming a library and place a range
> around its resolution.

I can not really agree with this as there are also a lot of authors of
libraries who do take versioning serious and who wouldn't, for example, break
API compatibility in a minor version. (e.g. between X.Y.Z and X.Y.Z+1 or even
X.Y+1). It would be wonderful if I, as a consumer or that library, could
simply state that my code works with all versions in the X.* version range
(but for example that it is not expected to work with X+1.*).

The specification of dependencies has to be done on a per-library basis and
will, naturally, take the versioning scheme of the specific library into
account. If I know that I can trust the author of the library to /not/ break
API compatibility in future minor releases I want to express that. I might
have even tested my code against a specific version range and want to
communicate that.

I think that the ability to specify ranges like this would actually increase
pressure to adhere to reasonable versioning schemes and, ultimately, even
better code in the community. (Simply because downstream consumers would
complain bitterly about API changes in minor releases that break their code).

> However, none of those standards apply in the commons, so ranges
> like the one that provoked the problem in this case ([org.clojure/clojure "
> [1.2,1.5)"]) are counterproductive (i.e. there is no reason to prospectively
> exclude an unreleased version unless you're certain that API changes will break
> the library in question).

I agree completely that it does not make sense to proactively /exclude/ a
specific unreleased version from being used, but it also doesn't make sense to
depend on *one* very specific version. It is also ridiculous that there is no
differentiation between release candidates and proper releases, but that is,
yet, another can of worms.

Things that most commonly have to be expressed are. for example, the
following:

* I need at least version 1.4 to work correctly and I know that everything
older than 2.0 won't work

* My library wraps the 3.* range of releases of the Java library
foo-to-be-wrapped and I have enough test cases to be sure of that



I would love if I wouldn't have to start every week with running "lein outdated"
and then guessing which of the libraries can be updated without breaking
something. I want my code to simply run on the newest version of the libraries
that I (and their upstream) support. If one of those versions breaks my code
that would be bug that has to be fixed.

I am well aware that the current toolset is not ideal for these situations and
that this is also a bit of a culture clash, but there is nothing inherently
wrong with being able to specify versions in a more expressive way. The
current toolset might not be ideal, but that is a problem of the toolset and
the way software is being distributed, not with the scheme itself.
signature.asc

Wolodja Wentland

unread,
Mar 4, 2013, 9:13:24 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 04, 2013 at 06:01 -0800, Meikel Brandmeyer (kotarak) wrote:
> Ok. So instead of the range I specify "[org.clojure/clojure "1.2"]". What does
> that mean? Now I either excluded *all* clojure versions not= 1.2 or the version
> number doesn't mean anything. Then we should get rid of it completely and just
> specify the dependency without it. (It seems there maven poms which do exactly
> that? o.O)
>
> The range [1.2;1.5) means that the library was tested with 1.2 up to 1.4 and -
> believing in semver - their patchlevel children. 1.5 (was at that time) not
> released, yet. So compatibility couldn't be guaranteed. For me this is a
> reasonable approach. Sure. It might work with 1.5. Everyone is free to place an
> exclusion to help the system resolve the conflict. But you must be aware you
> might run into trouble.
>
> If I follow your approach I must provide 4 branches of a library which
> basically consists of a single function: one branch per supported clojure
> version (so far). This is ridiculous. Or - as I said - we let all hope go and
> don't specify the version, only the dependency on the library itself.
>
> I see we have a different basic idea of what a version range should mean. For
> me it's a promise that my library will work with the versions specified. If one
> wants to use a version outside the range, that *might* be ok, but one should be
> aware and pointed to that fact and the decision to do so should be explicit!
>
> I'm probably just a pessimist, while you are an optimist.

Exactly! Thank you for stating this so clearly.
signature.asc

Michał Marczyk

unread,
Mar 4, 2013, 9:14:35 AM3/4/13
to clo...@googlegroups.com
On 4 March 2013 15:01, Meikel Brandmeyer (kotarak) <m...@kotka.de> wrote:
> The range [1.2;1.5) means that the library was tested with 1.2 up to 1.4 and
> - believing in semver - their patchlevel children. 1.5 (was at that time)
> not released, yet. So compatibility couldn't be guaranteed. For me this is a
> reasonable approach. Sure. It might work with 1.5. Everyone is free to place
> an exclusion to help the system resolve the conflict. But you must be aware
> you might run into trouble.

Better yet, you can specify a test matrix for your library. Of course
there's a bit of a combinatorial problem here, which however is not
solved by the version ranges: in fact to be thorough you should
probably run your tests with any valid selection of versions for the
dependencies -- imagine if you have ten ranges including two actually
released versions each specified in your project.clj...

But even overlooking that, using a baseline version and explicit tests
(or, failing that, a line in the README) to document what's the
minimum requirement and what has been tested seems sane to me *and* it
allows us to reuse the Maven infrastructure. What's there to be gained
by insisting on an improved version range handling?

Also, what impact would version ranges have on repeatability of builds?

Cheers,
M.

Marko Topolnik

unread,
Mar 4, 2013, 9:25:06 AM3/4/13
to clo...@googlegroups.com
On Monday, March 4, 2013 3:01:13 PM UTC+1, Meikel Brandmeyer (kotarak) wrote:

The range [1.2;1.5) means that the library was tested with 1.2 up to 1.4 and - believing in semver - their patchlevel children. 1.5 (was at that time) not released, yet. So compatibility couldn't be guaranteed. For me this is a reasonable approach. Sure. It might work with 1.5. Everyone is free to place an exclusion to help the system resolve the conflict. But you must be aware you might run into trouble.

This resembles Java's checked exceptions: "the user should be warned"; in reality it just causes frustrations. Libraries break even when they are within the declared range: nobody can predict all the interactions. On the other hand, most of the time an upgrade wouldn't hurt, but is prevented by a defensive version range, and this actually breaks down the whole build due to a lower bound by another library.

If a "feature" ends up having to be defused more often than it provides value, then it's not a feature. I second Chas' preference of "innocent until proven guilty" or, as you put it, "optimism". 

Wolodja Wentland

unread,
Mar 4, 2013, 9:30:38 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 04, 2013 at 15:04 +0100, Michał Marczyk wrote:

> On the other hand, if you care about securing your project, pulling in
> the latest bugfixes etc., you will need to monitor new releases
> anyway, regardless of the version numbering scheme used by their
> maintainers.

And then release a new version for every new release of one of my depedencies?

> > * Library authors would be more concerned about providing a stable
> > interface for all releases that fall into a certain version span
>
> Those library authors who care about this already act in this way.

Exactly and I would like to take advantage of this. I also think that
establishing reasonable versioning and using version ranges as the norm would
increase the pressure to, well, adhere to the norm by making sure that one
does not break backward compatibility in a minor release.

> > * Packaging software and tools by downstream distributions (e.g. Debian,
> > Ubuntu, …), so that Clojure software can be easily used by people that
> > are /not/ familiar with Clojure can still easily use software written in
> > it, would be much easier.
>
> Are people actually using package managers for Java libraries and
> applications much, beyond a small number of special cases like
> LibreOffice (which therefore can totally be packaged überjar-like)?

Yes, a lot of people don't really care in which language a tool is written
(nor should they) and simply want to install that software using their
preferred packaging system.

One reason for the need to not ship the same library all over again and in
using version ranges is one of security. Imagine if a library is found to be
buggy in version 1.2.3 and that a bugfix is available in 1.2.4. In order to
take advantage of this one can either upgrade that single library on a system
and /all other/ applications and libraries using this would be patched
immediately or you could force every consumer to change their dependency on
1.2.3 to 1.2.4 and release a new version.

> > * Deployment would be more predictable as people know that they target
> > only "stable" releases.

> In the absence of version ranges, that seems to be true today...?

Yes, it is. But then, the environment changes (see above), whereas some of
your assumptions about it might not.

To give an example: I could write code against the standard library that ships
with Python 2.7. I would expect that my code runs with all releases in the
2.7.* version range and would like to express that.

See, for example, http://www.python.org/dev/peps/pep-0426/#version-scheme
for a relevant PEP in the Python community and I am sure you'll find many
other examples for other languages.

> Here's a relevant link to a post on Yesod's blog from April 2012 (one
> of top Haskell web frameworks):
>
> http://www.yesodweb.com/blog/2012/04/cabal-meta
>
> And here's an interesting quote (again, this is from Yesod's own
> blog): "Even with all these tools, one day I found myself completely
> incapable of installng Yesod from source."
>
> I know Cabal is improving and it actually has a shot at solving some
> truly interesting problems with dependency handling, but right now I
> find it surprising that one could feel "spoiled" by using it to the
> point of feeling discomfort in Clojure land. (We actually have it
> simpler for example in that we don't have to deal much with
> assumptions baked into previously compiled artefacts; I'm not knocking
> Cabal here in any way, just noting that it's not all that rosy.)

Fair enough :)
signature.asc

David Powell

unread,
Mar 4, 2013, 9:42:56 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 4, 2013 at 2:01 PM, Meikel Brandmeyer (kotarak) <m...@kotka.de> wrote:
Hi Chas,

Am Montag, 4. März 2013 14:33:29 UTC+1 schrieb Chas Emerick:
There are a lot of reasons for this, but #1 for me is that few people understand the implications of version ranges, either downstream of their published libraries or when they are consuming a library and place a range around its resolution.  If you do, and your team does, then by all means, go hog-wild with version ranges in your in-house libraries and applications, where you can control versioning schemes, correspondences between APIs and versions, and so on.  However, none of those standards apply in the commons, so ranges like the one that provoked the problem in this case ([org.clojure/clojure "[1.2,1.5)"]) are counterproductive (i.e. there is no reason to prospectively exclude an unreleased version unless you're certain that API changes will break the library in question).  Granted, the fallback resolution of the Leiningen/Pomegranate/Aether triad fall down badly, which exacerbates the problem; again, that's being worked on, but the solution still won't help in this situation where a library blocks out e.g. 1.5.0, but a downstream user/library explicitly specifies 1.5.0.

Ok. So instead of the range I specify "[org.clojure/clojure "1.2"]". What does that mean? Now I either excluded *all* clojure versions not= 1.2 or the version number doesn't mean anything. Then we should get rid of it completely and just specify the dependency without it. (It seems there maven poms which do exactly that? o.O)

(Disclaimer - I'm no Maven expert) 

"1.2" in this case is a "soft" dependency on 1.2.  This is probably what you want.


This differs from "[1.2,1.5)", which is a hard dependency of 1.2 <= ver < 1.5

I don't know the exact details, but a soft dependency basically means, that the library would like 1.2, but if something else ends up requiring 1.3 or something, then that will be ok.  This way the top-level application can ultimately decide which versions are included.  This seems to be the most flexible, and repeatable option.


Version ranges aren't for communicating what versions of libraries you have tested against - that is best done out-of-band.  If you include a version range, like the one above, you are saying that you want the software to fail to build if something ends up requiring 1.5.  This probably isn't useful, as it will just lead to difficult to fix problems for library consumers.  I guess the only time you might want a maximum version to be specified, is if that version exists, and is known to be incompatible with your library.


Chas Emerick

unread,
Mar 4, 2013, 9:54:09 AM3/4/13
to clo...@googlegroups.com
AFAICT, the vast majority of Leiningen users (same goes for Maven users as well) expect the dependency vector [org.clojure/clojure "1.2.0"] to establish a lower bound, the equivalent of "[1.2.0,)".  Further, people expect the maximum of all overlapping requirements to be taken (so transitive dependencies requiring e.g. "1.2.0", "1.3.0", and "1.4.0" would resolve to "1.4.0"), and for the dependencies specified in the root of the tree (i.e. the current project.clj) to override everything else, so specifying "1.3.1" in the current project would be the equivalent of "[1.3.1]" (this is equivalent to having implicit dependencyManagement in Maven, for those that know/care what that means).

That's just my personal observation, but others that have done work in this area seem to agree on the general outline.  Further, it *should* be compatible with the existing Aether/Maven ecosystem that we're playing in; there, bare version numbers are purely advisory, so constraining them to set a lower bound is sane.  We'll see what happens when such a dependency resolution scheme is tested against the current defaults.

Re: what version numbers *should* mean, etc., at least when it comes to publicly-published libraries: I don't think it's a matter of optimism vs. pessimism.  A minor point is that, if you release a library with a constraint of [1.2.0,1.5.0), then to get an updated version that has an updated constraint, users may (will inevitably) have to swallow API or semantic changes that are orthogonal to the notion of "tested with".  More importantly, users of libraries are always going to upgrade their dependencies faster than those dependencies' authors can qualify new releases against *their* dependencies.  Indeed, given the way things work these days, projects constantly rely upon others' rarely-maintained work: people's interests and priorities shift, but if their libraries continue to work, then requiring everyone else to either wait for a new release (and for all intervening transitive dependencies to update accordingly) or manually override version ranges is counterproductive.  Signal re: breakage caused by some version X of a library will always propagate faster (and probably more accurately) by users bumping into things than by a careful author validating correctness.

See how it's worked in the current case: as active as you are in the Clojure community Meikel, your users have outpaced you.  The same happens to all of us, all the time.  :-)

I agree that some indication of which libraries have been tested with which dependencies would be *great*.  But that's part of a wide class of verification objectives I think that must be totally separate use cases from the (relatively) simple dependency resolution one that version numbers aim to support.

Cheers,

- Chas

Wolodja Wentland

unread,
Mar 4, 2013, 9:55:01 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 04, 2013 at 14:42 +0000, David Powell wrote:

> "1.2" in this case is a "soft" dependency on 1.2.  This is probably what you
> want.
>
> <http://docs.codehaus.org/display/MAVEN/
> Dependency+Mediation+and+Conflict+Resolution#
> DependencyMediationandConflictResolution-DependencyVersionRanges>

Then why declare a versioned dependency in the first place?
signature.asc

Marko Topolnik

unread,
Mar 4, 2013, 9:59:32 AM3/4/13
to clo...@googlegroups.com
On Monday, March 4, 2013 3:42:56 PM UTC+1, David Powell wrote:

Version ranges aren't for communicating what versions of libraries you have tested against - that is best done out-of-band.  If you include a version range, like the one above, you are saying that you want the software to fail to build if something ends up requiring 1.5.  This probably isn't useful, as it will just lead to difficult to fix problems for library consumers.

The left-bounded, right-unbounded range seems to be the best practice since we always know the lowest acceptable version. 
 
I guess the only time you might want a maximum version to be specified, is if that version exists, and is known to be incompatible with your library.

Even here we shouldn't be too eager: only if the official API of a dependency acquires a breaking change should we use an upper bound; if there's just a single version out there that fails due to a bug, no action should be taken.

-Marko

David Powell

unread,
Mar 4, 2013, 10:01:12 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 4, 2013 at 2:55 PM, Wolodja Wentland <bab...@gmail.com> wrote:
On Mon, Mar 04, 2013 at 14:42 +0000, David Powell wrote:

> "1.2" in this case is a "soft" dependency on 1.2.  This is probably what you
> want.
>
> <http://docs.codehaus.org/display/MAVEN/
> Dependency+Mediation+and+Conflict+Resolution#
> DependencyMediationandConflictResolution-DependencyVersionRanges>

Then why declare a versioned dependency in the first place?

It effectively declares a lower-bound on the version number.

-- 
Dave

Wolodja Wentland

unread,
Mar 4, 2013, 10:15:22 AM3/4/13
to clo...@googlegroups.com
On Mon, Mar 04, 2013 at 09:54 -0500, Chas Emerick wrote:
> AFAICT, the vast majority of Leiningen users (same goes for Maven users as
> well) expect the dependency vector [org.clojure/clojure "1.2.0"] to establish a
> lower bound, the equivalent of "[1.2.0,)". Further, people expect the maximum
> of all overlapping requirements to be taken (so transitive dependencies
> requiring e.g. "1.2.0", "1.3.0", and "1.4.0" would resolve to "1.4.0"), and for
> the dependencies specified in the root of the tree (i.e. the current
> project.clj) to override everything else, so specifying "1.3.1" in the current
> project would be the equivalent of "[1.3.1]" (this is equivalent to having
> implicit dependencyManagement in Maven, for those that know/care what that
> means).

[…]

> I agree that some indication of which libraries have been tested with which
> dependencies would be *great*. But that's part of a wide class of verification
> objectives I think that must be totally separate use cases from the
> (relatively) simple dependency resolution one that version numbers aim to
> support.

Thanks for this mail! I think it is very helpful in the debate. The notion of
"soft dependencies" seems to be quite ridiculous (as you could just have an
unversioned one), but the real problem seem to be that there is no way to
express the notion of:

I (should) work with all stable releases in the 1.4.* branch of libfoo

among many other reasonable schemes.
signature.asc

Michał Marczyk

unread,
Mar 4, 2013, 11:27:28 AM3/4/13
to clo...@googlegroups.com
On 4 March 2013 15:30, Wolodja Wentland <bab...@gmail.com> wrote:
> On Mon, Mar 04, 2013 at 15:04 +0100, Michał Marczyk wrote:
>
>> On the other hand, if you care about securing your project, pulling in
>> the latest bugfixes etc., you will need to monitor new releases
>> anyway, regardless of the version numbering scheme used by their
>> maintainers.
>
> And then release a new version for every new release of one of my depedencies?

For a security fix, absolutely (although the users should upgrade the
dependency on their side as soon as they learn about the problem
anyway). For a different bug fix, maybe, depending on if you care
about the bug.

>> > * Library authors would be more concerned about providing a stable
>> > interface for all releases that fall into a certain version span
>>
>> Those library authors who care about this already act in this way.
>
> Exactly and I would like to take advantage of this. I also think that
> establishing reasonable versioning and using version ranges as the norm would
> increase the pressure to, well, adhere to the norm by making sure that one
> does not break backward compatibility in a minor release.

You can take advantage of this by using the new versions without
changing your old code. Having this happen automatically -- as in,
1.4.0 gets pulled during the build on Monday, then 1.4.1 on Tuesday
with no explicit action to cause it on your part -- means throwing
away repeatability of your top-level build. I'm just not convinced
that is a good idea.

> Yes, a lot of people don't really care in which language a tool is written
> (nor should they) and simply want to install that software using their
> preferred packaging system.

Sure, and there's no problem with that:

> One reason for the need to not ship the same library all over again and in
> using version ranges is one of security. Imagine if a library is found to be
> buggy in version 1.2.3 and that a bugfix is available in 1.2.4. In order to
> take advantage of this one can either upgrade that single library on a system
> and /all other/ applications and libraries using this would be patched
> immediately or you could force every consumer to change their dependency on
> 1.2.3 to 1.2.4 and release a new version.

The version used by an app is just the version in the jar put on the
classpath by its launcher. For packaged apps, this will tend to be a
symlink to some sort of "latest in the 1.4.x branch" release jar. The
story for .so files is exactly the same (there's tons of symlinks in
/usr/lib on an Ubuntu system).

And what happens if 1.4.8 actually breaks compatibility with 1.4.7
while introducing a security fix? Well, if you're maintaining the
package, you might actually backport the fix.

Of course that's not very relevant to lots of Clojure software written
today to be deployed to a server / "cloud" / run locally to crunch
some data etc. where I have see no problem with simply updating the
top-level project.clj / pom.xml.

> To give an example: I could write code against the standard library that ships
> with Python 2.7. I would expect that my code runs with all releases in the
> 2.7.* version range and would like to express that.
>
> See, for example, http://www.python.org/dev/peps/pep-0426/#version-scheme
> for a relevant PEP in the Python community and I am sure you'll find many
> other examples for other languages.

Is it typical of Python packages to use non-trivial ranges? (As in,
version specifiers which are not either == or purely >=.) The handful
of packages I've examined tend to be apps and use == or libraries and
use >= with no upper bound.

I do recall that pip, virtualenv & friends allow one to pull in the
latest versions of packages easily -- and then to freeze the
requirements for deployment, thereby avoiding headaches with the
equivalent of non-repeatable builds.

On 4 March 2013 16:15, Wolodja Wentland <bab...@gmail.com> wrote:
> On Mon, Mar 04, 2013 at 09:54 -0500, Chas Emerick wrote:
> […]
>
> Thanks for this mail! I think it is very helpful in the debate. The notion of
> "soft dependencies" seems to be quite ridiculous (as you could just have an
> unversioned one), but the real problem seem to be that there is no way to
> express the notion of:
>
> I (should) work with all stable releases in the 1.4.* branch of libfoo
>
> among many other reasonable schemes.

I'd say you do this by including [libfoo "1.4.0"] in your
:dependencies. If your library then breaks because 1.4.8 comes out
with a breaking change and some project's will have both libfoo-1.4.8
and your library on the classpath, then that is libfoo's fault.

Wrapping up, I'd say that using version ranges feels like imposing
something like semver on your dependencies. Unless you maintain those
dependencies, you simply can't do it. If they follow the convention,
you can take advantage and upgrade to new releases with ease; if they
don't, there's no value in writing down an expectation to the contrary
in your build spec.

Cheers,
Michał

Nelson Morris

unread,
Mar 20, 2013, 4:20:00 PM3/20/13
to clo...@googlegroups.com
In lein 2.1 using `lein deps :tree` will print out any version ranges
it finds. Hopefully this helps with when noticing similar dependency
issues.
Reply all
Reply to author
Forward
0 new messages