If you are unhappy with the direction of Ruby 1.8.7+, respond

2009/2/13 James C. [email protected]:

demonstrate that it gives a **** about order of appearance
in a literal, or insertion order.

I’m really not up for a slanging match so let me just say that, in code I’ve
written, Ruby < 1.8.7 has demonstrated the behaviour I described. This may
be a fluke or a bug, in which case I will investigate further and file bugs
if necessary.

I can tell you how such a bug report would look like:

Bug: In Ruby 1.8.x Hash iteration order .....

Rejected: Hash iteration order in 1.8 is undefined.

What I do know is that I’ve had code in a library released
over 2 years ago and used by a fair number of people relying on this
behaviour and heard no complaints until 1.8.7 arrived.

A hidden bug in your code because of an incorrect assumption.

I realise that
hashtables are not ordered in 1.8 and have since made my code more robust.
I’m not questioning your examples – …

You seem to be ignoring them.

… you can but experiment to see what
works – and I will try to extract the code from my project that
demonstrates my point when I have some time.

I’m not the least bit interested in who’s right or wrong or in berating the
Ruby code devs or indeed anyone else, and was hoping for a productive
discussion, not people repeatedly asserting that I don’t know how a hash
table works and trying to shut me up. When I’ve time I’ll see if what I have
is a Ruby bug or something else. Until then I’m canning this conversation.

I and others here took the trouble finding out and explaining
why your code failed. That’s a productive discussion. You’d just
have to accept that it’s your code that was buggy. There’s
nothing bad about that. Everybody writes buggy code sometimes.

Instead you keep looking for a bug in Ruby that doesn’t exist,
as has been clearly proven.

Stefan

On Feb 13, 11:11 am, Rick DeNatale [email protected] wrote:

unfortunate, caused by Rails’ fragile monkey patching and our bad

Rails 2.2 is now compatible with Ruby 1.8.7 it has taken work, and new
releases, from both the Ruby team and the Rails team.

Well, it’s frustrating for me. My ISP just sent word:

We will be upgrading your server to the following versions of Ruby
and Rails on Wednesday, February 18, 2009.

Ruby 1.8.7
Rails 2.2.2

This upgrade is needed to bring Ruby and Rails to the current stable
releases.

I’m wondering what it’s going to take to get to 1.9. That’s were I
want to go. But now I have to horse around in 1.8 and 1.8.7 for who
knows how long.

The switch from 1.6 to 1.8 went much more smoothly. If Rails were
around back then, I wonder if we would still be deal with 1.6.9 today?

I think 1.8.7 was a mistake. It has taken us too long to get to 1.9
and now we are being forced to deal with a unwanted stop-gap measure,
holding it all up yet again.

T.

No, it’s not a gray area. Anyone who has a basic understanding of
hash-tables doesn’t even think about the iteration order.

There’s a big difference between abstract computer science theory and
pragmatic
technology.

Ruby uses option-hashes as an emergent “named parameters” system. We
have
hundreds of DSLs written with them.

After these DSLs can see the order that the user-programmer wrote the
parameters, they are free to use this order to grow more powerful.

Pit C. wrote:

2009/2/12 Gregory B. [email protected]:

On Thu, Feb 12, 2009 at 1:59 PM, Pit C. [email protected] wrote:

Gregory, there is no Ruby 1.8 and has never been. There have been
1.8.0, 1.8.1, up to 1.8.7, each one differing from the others.

You keep saying this but frankly, it’s ridiculous. Yes, you can find
changes. In Ruby 1.8.7, you get clubbed over the head with them.

So we agree to disagree. Though I’d be interested in what you’d define
as “Ruby 1.8”. Is it 1.8.6? Why not 1.8.2? Does 1.8.5 qualify as being
a “Ruby 1.8”, despite the differences to 1.8.6?

Until now, it didn’t matter. Most code written under 1.8.6 ran quite
happily under 1.8.5 or 1.8.2, unless it exercised a few specific bugs or
a few edge cases of feature enhancements.

Example: TCPSocket.new now accepts up to 4 arguments instead of just 2.
However few people use the functionality (for binding to an explicit
local IP and/or port). Those who do will need to run the later version
of Ruby.

IMO, the biggest problem with 1.8.7 is that people are getting it
installed by default (e.g. in newer Debian/Ubuntu systems). They are
starting to write code using a whole heap of new features in 1.8.6,
sometimes by accident. This code will not run on production 1.8.6
platforms. Once library writers start doing this, it messes up the whole
library ecosystem.

Ola B. wrote:

What about 1.8.6.1?

As much as I dislike the patchlevel concept, it would be very cumbersome
to change it now and have a fourth digit. Rubyspec would have to change,
other implementations would have to change…consider the patchlevel
number as the fourth digit and just continue to increment it.

  • Charlie

Nobuyoshi N. wrote:

Hi,

At Fri, 13 Feb 2009 02:36:06 +0900,
Rick DeNatale wrote in [ruby-talk:327919]:

Although, I’m at a loss as to what you’d use for the version number on the
first maintenance release.

1.8.6-p###.

Agreed, just to make more noise about this. The p-numbers aren’t great
(they could have just been a fourth digit) but moving to a fourth digit
now would cause mass confusion.

Which do I install, 1.8.6-p287 or 1.8.6.1?

  • Charlie

M. Edward (Ed) Borasky wrote:

Someone suggested having 1.8.8 being 1.8.6 syntax and semantics with
only bug fixes, security fixes and efficiency enhancements. That appeals
to me … that way, “1.8.7” is a development release and “1.8.8” is
stable. But I would think EngineYard would want to “brand” their ruby
1.8.6 implementation in a manner similar to Ruby Enterprise Edition.

IMHO, Engine Y. should not take over Ruby 1.8.6 to take it in new
directions, they are just becoming 1.8.6 maintainers. I agree with
Matz that any large-scale changes like REE or other stuff should still
filter down the 1.8 mainline chain.

And look at it this way…the non-Japanese community has perhaps not had
enough say in the direction of 1.8…we don’t want to turn around and do
the same thing. If EY becomes 1.8.6 maintainers, they should not repeat
mistakes and make sure the rest of ruby-core and the Japanese Ruby
community are on board with all 1.8.6 revisions.

  • Charlie

Yukihiro M. wrote:

then merged back into 1.8.6 if appropriate. I am not going to allow
EngineYard to fork off 1.8.6. If people from EngineYard want to
improve 1.8, it’s OK. We are open. I will give them commit privilege
even. But no fork.

Agreed here…1.8.6 should become more stable, and all changes should
filter down throught the 1_8 branch on ruby-lang. 1.8.6 should not
start to incorporate fixes/enhancements that are not in the other 1_8
versions.

  • Charlie

On Fri, Feb 13, 2009 at 8:41 PM, Trans [email protected] wrote:

I think 1.8.7 was a mistake. It has taken us too long to get to 1.9
and now we are being forced to deal with a unwanted stop-gap measure,
holding it all up yet again.

It indeed was, though technically fine! It seems that it killed its
sibling. :frowning:
R.

+1

2009/2/13 James C. [email protected]:

I’m really not up for a slanging match so let me just say that, in code I’ve
written, Ruby < 1.8.7 has demonstrated the behaviour I described.

This is just not true. Period. And I can prove it.

This is an excerpt from a previous version of your code:

DICTIONARY = RegexpGroup.new({
:OPERATOR => /return|typeof|[[(^=,{}:;&|!?]/.source,
:CONDITIONAL => //*@\w
|\w*@*/|//@\w*|@\w+/.source,
:COMMENT1 => ///[^\n]/.source,
:COMMENT2 => //*[^
]*+([^/][^]*+)//.source,
:REGEXP => //(\[/\]|[^/])(\.|[^/\n\])/[gim]/.source,
:STRING1 => /'(\.|[^'\])
'/.source,
:STRING2 => /“(\.|[^”\])*"/.source
})

You say that in 1.8.6 the iteration order of the resulting hash has
been the same as the order in the hash literal, but look at the
following output:

puts DICTIONARY
=>
(COMMENT1)|(COMMENT2)|(STRING1)|(STRING2)|(CONDITIONAL)|(OPERATOR)|(REGEXP)

As you can see, the iteration order is completely different from the
order in the hash literal. I really don’t know what made you think
that 1.8.6 was using insertion order.

What I do know is that I’ve had code in a library released
over 2 years ago and used by a fair number of people relying on this
behaviour and heard no complaints until 1.8.7 arrived.

Your code was working by accident. Read along:

I realise that
hashtables are not ordered in 1.8 and have since made my code more robust.

You noticed that the iteration order had changed in 1.8.7, so you
changed your code to:

DICTIONARY = RegexpGroup.new.
put(:OPERATOR, /return|typeof|[[(^=,{}:;&|!?]/.source).
put(:CONDITIONAL, //*@\w
|\w*@*/|//@\w*|@\w+/.source).
put(:COMMENT1, ///[^\n]/.source).
put(:COMMENT2, //*[^
]*+([^/][^]*+)//.source).
put(:REGEXP,
//(\[/\]|[^/])(\.|[^/\n\])/[gim]/.source).
put(:STRING1, /'(\.|[^'\])
'/.source).
put(:STRING2, /“(\.|[^”\])*"/.source)

I don’t know whether this change made a difference on 1.8.7. It
definitely had no effect on the iteration order, neither in 1.8.7 nor
in 1.8.6:

puts DICTIONARY
=>
(COMMENT1)|(COMMENT2)|(STRING1)|(STRING2)|(CONDITIONAL)|(OPERATOR)|(REGEXP)

Now you might say that on your machine and with your version of Ruby
the iteration order had been different and that in your environment
the iteration order still had been the same as the literal order. But
that is not true. Read on:

I will try to extract the code from my project that
demonstrates my point when I have some time.

No need to do that. I fixed some bugs in your code so that the
iteration order is really the same as the literal order:

puts DICTIONARY
=>
(OPERATOR)|(CONDITIONAL)|(COMMENT1)|(COMMENT2)|(REGEXP)|(STRING1)|(STRING2)

And guess what? Your code stopped working! Your code only works with
the iteration order of 1.8.6. The iteration order must be different
from insertion order, or else your code doesn’t work.

Now please stop talking about 1.8.6 having some well defined property
that has been changed in 1.8.7. This simply is not true.

I’m not the least bit interested in who’s right or wrong or in berating the
Ruby code devs or indeed anyone else, and was hoping for a productive
discussion (…)

OK. You said in a previous post that you still had one problem with
regular expressions in 1.8.7. In reality, the bug had nothing to do
with regular expressions, but with … guess what? … the iteration
order of hashes. If you carefully build all the hashes in the same
order as those you got with Ruby 1.8.6, then all your tests are
working on both 1.8.6 and 1.8.7.

I don’t know git, but if you tell me how, I can send you the two bug
fixes and the working hash sequences. I’d suggest that you take a
careful look at those sequences, whether they are as you want them to
be, because they look really weird.

Regards,
Pit

In article
[email protected],
Pit C. [email protected] writes:

})
Symbol#hash is fragile.

% ruby-1.8.6p287 -e ‘p :a.hash’
104738
% ruby-1.8.6p287 -e ‘:x; p :a.hash’
104818

The :x expression, which seems have no side-effect, affects
:a.hash.

This is because Symbol#hash depends on how many symbols
known when the symbol first appeared.

This value affects the bucket of a hash. So it affects the
iteration order, until ruby 1.8.

It also depends on ruby version.

% all-ruby -e ‘p :a.hash’
ruby-1.4.6(2000-08-16) 8593
ruby-1.6.0(2000-09-19) 2281742
ruby-1.6.1(2000-09-27) 2281742
ruby-1.6.2(2000-12-25) 2291982
ruby-1.6.3(2001-03-19) 2294030
ruby-1.6.4(2001-06-04) 2294030
ruby-1.6.5(2001-09-19) 2294030
ruby-1.6.6(2001-12-26) 2296078
ruby-1.6.7(2002-03-01) 2302222
ruby-1.6.8(2002-12-24) 2308366
ruby-1.8.0(2003-08-04) 2605326
ruby-1.8.1(2003-12-25) 2609422
ruby-1.8.2(2004-12-25) 2619662
ruby-1.8.3(2005-09-21) 2625806
ruby-1.8.4(2005-12-24) 2625806
ruby-1.8.5(2006-08-25) 104018
ruby-1.8.5p52(2007-06-07) 104178
ruby-1.8.5p113(2007-09-23) 104178
ruby-1.8.5p115(2008-03-03) 104178
ruby-1.8.5p231(2008-06-20) 104178
ruby-1.8.5head(2008-06-20p231) 104178
ruby-1.8.6p0(2007-03-13) 104738
ruby-1.8.6p36(2007-06-07) 104738
ruby-1.8.6p110(2007-09-23) 104738
ruby-1.8.6p111(2007-09-24) 104738
ruby-1.8.6p114(2008-03-03) 104738
ruby-1.8.6p230(2008-06-20) 104738
ruby-1.8.6p287(2008-08-11) 104738
ruby-1.8.6head(2009-02-13p330) 104738
ruby-1.8.7p0(2008-05-31) 109218
ruby-1.8.7p17(2008-06-09) 109218
ruby-1.8.7p22(2008-06-20) 109218
ruby-1.8.7p72(2008-08-11) 109218
ruby-1.8.7head(2009-02-13p116) 109218
ruby-1.8(2009-02-05r22080) 109938
ruby-1.9.1p0(2009-01-30r21907) 117848
ruby-1.9(2009-02-14r22297) 118088

It seems ruby-1.8.7 changes the value, as well as other many
versions.

The changes are because the number of symbols used
internally, algorithm changes, etc.

Symbol#hash is fragile. Too dangerous to depend.

In general, the algorithm of #hash methods (not only
Symbol#hash) is ruby internal. Don’t depend on that.

On Feb 13, 7:11 am, Jean-Denis M.

My point is that we programmers have grown to expect string comparison to
work in the incorrect way, to the point that you now claim that the
desired behaviour is the wrong one. My claim is that the desired
behaviour is for “1.8.10” to sort after “1.8.9”.

Absolutely not.
That would be desired only when 10 and 9 are numbers,
not strings.

[ “1.8.10”, “1.8.9” ].sort_by{|s| s.split(".").map{|x| x.to_i}}
==>[“1.8.9”, “1.8.10”]

  My mother and my

grandfather agree.

I’ll wager they are piss-poor programmers.

And no, I don’t suggest we redefine string comparison in Ruby at this point
in time.

Later, you mean?

On 2/13/09 1:00 AM, “[email protected]
[email protected] wrote:

From: Yossef M. [email protected]
[…]
find it dismaying that anyone would seriously say that this isn’t
desired string comparison behavior. I mean, these are strings, not
anything special. They just happen to contain a certain pattern of
characters.

Well, I am seriously suggesting just that.

And I am not alone. The Mac Finder will “alphabetically” list files
named
1.8.8, 1.8.9 and 1.8.10 in that order.

Moreover, in MacRuby, I can do:

framework ‘Cocoa’
=> true
a=“1.8.8”
=> “1.8.8”
b=“1.8.9”
=> “1.8.9”
c=“1.8.10”
=> “1.8.10”
a.compare b, options:NSNumericSearch
=> -1
b.compare c, options:NSNumericSearch
=> -1

Before you point it out, yes, the NSNumericSearch constant option must
be
passed to compare for that to work that way. Without it, compare returns
the
result you expect.

My point is that we programmers have grown to expect string comparison
to
work in the incorrect way, to the point that you now claim that the
desired behaviour is the wrong one. My claim is that the desired
behaviour is for “1.8.10” to sort after “1.8.9”. My mother and my
grandfather agree.

And no, I don’t suggest we redefine string comparison in Ruby at this
point
in time.

As for the issue at hand, a good solution was proposed.

William J. wrote:

Normal hash-tables are ordered nowhere, no-how, and no-way.

A 9-year-old boy wanted to keep track of the color of his
toys. He wrote “car: red” on a piece of paper which he then
put in a bag. Then he did the same with “airplane: silver”
and “ball: blue”. Days later, he decided to review the data.
He reached into the bag and pulled out a slip. It didn’t
say “car”! It was the slip with the color of the ball!
The slips were coming out in the wrong order!

There’s a big difference between abstract computer science theory and
pragmatic
technology.

Ruby uses option-hashes as an emergent “named parameters” system. We
have
hundreds of DSLs written with them.

After these DSLs can see the order that the user-programmer wrote the
parameters, they are free to use this order to grow more powerful.

Just because one (technological) implementation of hash tables throws
information away, that does not mean it was required to throw that
info away.

How about we give you your own special version,
HashWithIndifferentOrder, that
guarantees it randomizes key order?

And along the way, we can give you := for assignment, and = to test
equality,
because - you know - the = operator has always meant equality, not
assignment.

I don’t know git, but if you tell me how, I can send you the two bug
fixes and the working hash sequences. I’d suggest that you take a
careful look at those sequences, whether they are as you want them to
be, because they look really weird.

That would be wonderful, thank you. Just email patches to
[email protected], or send me an archive with all the working code
if
diffs are a problem.

Seems I somehow gave the impression that I think my code is perfect and
that
Ruby is broken. All I wanted to do was point out a change and ask for
help
fixing my code. Shooting down assertions as untrue when they’re based on
working code is not helpful. I realise it’s easy to misappropriate the
cause
of bugs sometimes but it’s far more helpful to help the author
investigate
the cause, rather than just telling them their examples are wrong and
questioning their knowledge. This list is usually in the friendly and
helpful end of the spectrum but this thread seems to have taken the tone
down a couple notches.

One final thing: someone mentioned that ordered hashes had been
backported
to 1.8.7 but others disagree. Could someone from the core team settle
this
one?

William J. wrote:

only on the hash function and its inputs. It doesn’t know
case I will investigate further and file bugs if necessary.
Normal hash-tables are ordered nowhere, no-how, and no-way.
asserting that I don’t know how a hash table works
say “car”! It was the slip with the color of the ball!
The slips were coming out in the wrong order!
Devestated, he began crying and ran to his mommy.

Um, how is bag[“car”] implemented? How is this analogous with a hash? Do
you understand how a hash-table works? (Yes, I know you do.)

Phlip wrote:

Ruby uses option-hashes as an emergent “named parameters” system. We
have hundreds of DSLs written with them.

Granted.

After these DSLs can see the order that the user-programmer wrote the
parameters, they are free to use this order to grow more powerful.

How so?

I honestly can’t think of a case where I’d want to do that. If I wanted
positional arguments, I’d use them. If I want named arguments, why do I
care about their position?

Just because one (technological) implementation of hash tables throws
information away, that does not mean it was required to throw that
info away.

No, but it’s very likely more efficient to do so, and the vast majority
of hashes simply do not need that information.

How about we give you your own special version,
HashWithIndifferentOrder, that guarantees it randomizes key order?

Because most hashes don’t need them?

There are several OrderedHash implementations, some of them quite old,
if you really want to depend on hash ordering.

And along the way, we can give you := for assignment, and = to test
equality, because - you know - the = operator has always meant
equality, not assignment.

Ew. I see your point, but I find I do a lot more assignments than tests
for equality, so I prefer less typing for that.

Also not sure what this has to do with the other discussion…

Hi –

On Sat, 14 Feb 2009, James C. wrote:

One final thing: someone mentioned that ordered hashes had been backported
to 1.8.7 but others disagree. Could someone from the core team settle this
one?

1.8.7 can settle it :slight_smile:

irb(main):001:0> RUBY_DESCRIPTION
=> “ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-solaris2.11]”
irb(main):002:0> {3,4,1,2}.first
=> [1, 2]

David


David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.rubypal.com
Coming in 2009: The Well-Grounded Rubyist (The Well-Grounded Rubyist)

http://www.wishsight.com => Independent, social wishlist management!

On Feb 11, 12:10 pm, Gregory B. [email protected] wrote:

This one is for those who wish that Ruby 1.8 would go back to being
1.8.6 compatible in Ruby 1.8.8. If you agree with this, share your
thoughts or at least a simple ‘+1’.

+1000

We have a reasonable-sized body of code on 1.8.7, in production, that
we will not expect to upgrade for a minor release.

We expect some compatibility issues with an 1.8 → 1.9 upgrade.

We expect there will be many issues with an 1.8 → 2.0 upgrade.

I have been developing software and managing the development process
for almost 30 years, and this issue of an incompatible minor release
is a huge violation of the Principle of Least Surprise.

If this trend is followed, that of capriciously breaking compatibility
on minor point releases, then the language usage rate will diminish,
adoption rate will decrease, and the language will become
marginalized.

People only have so much time and effort to work on problems. A
programming language is a tool to solve those problems. If the tool
causes MORE work, then another tool will be chosen instead.

It’s really pretty simple.