7

The gemspec semantic versioning operator ~> (aka twiddle-wakka, aka pessimistic operator) allows a gem version to be constrained yet allow some upgrades.

I have often seen that it can be read as:

 "~> 3.1"   => "Any version 3.x, but at least 3.1"
 "~> 3.1.1" => "Any version 3.1.x, but at least 3.1.1"

But with one number, this rule breaks down:

 "~> 3"     => "Any version x, but at least 3"   *NOT TRUE!*
 "~> 3"     => "Any version 3.x"                 *True. But why?*

If I wanted "Any version 3.x", I could just use "~> 3.0", which is consistent. As it stands, this change of operation at one number is inconsistent and undocumented.

Moreover, if I wanted to say "Any version higher than or equal to 3" (so 3.x, 4.x etc...) I am tempted to use the ">=" operator, which we are told is evil.

Is there a reason for this behaviour?

EDIT:

I'm giving this to David for finding the culprit file in rubygems. There is a "feature" that silently expands "3" to "3.0" (Line 148 in version.rb: "single-digit versions are automatically extended with a zero to give a sensible result.")

I must say I disagree that the result is sensible, as it breaks the expected sequence, and prevents being able to say "Any version x, but at least 3" with that operator. Thus, we are forced onto >= which guides.rubygems.org warns us not to use. Anyway. Maybe this post will serve as the documentation I'd been looking for...

hlascelles
  • 1,061
  • 11
  • 15

1 Answers1

6

By peeking into rubygems sources (esp. requirement.rb, version.rb) the pessimistic operator needs at least two versioning segments.

It also does make a sense. As ~> v.r is just a syntactic sugar for inequality

v.r <= current_version.current_release < (v+1).0

what would be the upper bound if there is only one version number ? Yep, ∞ (infinity), so there is no point why it should work. You can simply write it as >= v .

David Unric
  • 7,421
  • 1
  • 37
  • 65
  • 3
    That equation makes more sense than other blog posts or documentation I've seen. Certainly no-one refers to the auto-conversion of "3" to "3.0". Kudos for the code diving (Line 148 in version.rb specifically: "single-digit versions are automatically extended with a zero to give a sensible result.") – hlascelles Jun 09 '14 at 18:02
  • @hlascelles Good find. It complements the statement about requirement of two version segments for `~>` operator. I'd also agree the automatic conversion is not too intuitive. – David Unric Jun 09 '14 at 20:07