Map keys and values behavior

I am working on the JRuby project and I was running some of the tests
in samples/test.rb from main ruby-1.8.1 source. I ran across something
which seems like a bug to me (in the test). It is something like:

$y = {1, 2, 2, 4, 3, 6}
test_ok($y.keys, [1,2,3])
test_ok($y.values, [2,4,6])

  Does ruby Maps really return keys and values in order of insertion?
That seems strange to me. Seems like the tests are missing a sort.

-Tom

···

--
+ http://www.tc.umn.edu/~enebo +---- mailto:enebo@acm.org ----+

Thomas E Enebo, Protagonist | "A word is worth a thousand |
                             > pictures" -Bruce Tognazzini |1

Thomas E Enebo wrote:

I am working on the JRuby project and I was running some of the tests
in samples/test.rb from main ruby-1.8.1 source. I ran across

something

which seems like a bug to me (in the test). It is something like:

$y = {1, 2, 2, 4, 3, 6}
test_ok($y.keys, [1,2,3])
test_ok($y.values, [2,4,6])

  Does ruby Maps really return keys and values in order of insertion?

It might or it might not. But in general no.

That seems strange to me. Seems like the tests are missing a sort.

$ ruby -v
ruby 1.8.2 (2004-12-25) [i386-cygwin]
$ irb
irb(main):001:0> h = {1=>2, 2=>4, 3=>6}
=> {1=>2, 2=>4, 3=>6}
irb(main):002:0> h.keys
=> [1, 2, 3]
irb(main):003:0> h.values
=> [2, 4, 6]
irb(main):004:0> 3.hash
=> 7

In the above example the keys are in order, but that is only because
Ruby's hash's hashing algorithm. Fixnums hash to themself (Hash does
not call Fixnum#hash to save time, so 3.hash really == 3). Then (I
think, see st.c to verify) when the Hash is iterated over (to collect
the keys, values, etc) it is traversed in the order of the hash of the
keys.

Here is another example:
irb(main):003:0> "a".hash
=> 100
irb(main):004:0> "b".hash
=> 101
irb(main):005:0> h = {"a"=>1, "b"=>2}
=> {"a"=>1, "b"=>2}
irb(main):006:0> h.keys
=> ["a", "b"]
irb(main):007:0> h.values
=> [1, 2]
### Now try in different order ###
irb(main):008:0> h = {"b"=>2, "a"=>1}
=> {"a"=>1, "b"=>2}
irb(main):009:0> h.keys
=> ["a", "b"]
irb(main):010:0> h.values
=> [1, 2]

100 comes before 101.

-Charlie

"Thomas E Enebo" <enebo@acm.org> schrieb im Newsbeitrag
news:20050208180232.GH20797@garnet.tc.umn.edu...

  I am working on the JRuby project and I was running some of the tests
in samples/test.rb from main ruby-1.8.1 source. I ran across something
which seems like a bug to me (in the test). It is something like:

$y = {1, 2, 2, 4, 3, 6}
test_ok($y.keys, [1,2,3])
test_ok($y.values, [2,4,6])

  Does ruby Maps really return keys and values in order of insertion?

No.

That seems strange to me. Seems like the tests are missing a sort.

Yes. Or you do a more complex type of test that ensures that all values
from the test array are contained in #values.

Kind regards

    robert

Charles Mills wrote:

Thomas E Enebo wrote:
> I am working on the JRuby project and I was running some of the

tests

> in samples/test.rb from main ruby-1.8.1 source. I ran across
something
> which seems like a bug to me (in the test). It is something like:
>
> $y = {1, 2, 2, 4, 3, 6}
> test_ok($y.keys, [1,2,3])
> test_ok($y.values, [2,4,6])
>
> Does ruby Maps really return keys and values in order of

insertion?

It might or it might not. But in general no.

> That seems strange to me. Seems like the tests are missing a sort.
>
$ ruby -v
ruby 1.8.2 (2004-12-25) [i386-cygwin]
$ irb
irb(main):001:0> h = {1=>2, 2=>4, 3=>6}
=> {1=>2, 2=>4, 3=>6}
irb(main):002:0> h.keys
=> [1, 2, 3]
irb(main):003:0> h.values
=> [2, 4, 6]
irb(main):004:0> 3.hash
=> 7

In the above example the keys are in order, but that is only because
Ruby's hash's hashing algorithm. Fixnums hash to themself (Hash does
not call Fixnum#hash to save time, so 3.hash really == 3).

Never mind, 3.hash == (3 << 1) + 1
Which equals LONG2FIX(3). So at the C level Hash doesn't have to call
Fixnum#hash because the Ruby representation is the hash of the Fixnum
or visa versa or something...

Then (I
think, see st.c to verify) when the Hash is iterated over (to collect
the keys, values, etc) it is traversed in the order of the hash of

the

···

keys.

Here is another example:
irb(main):003:0> "a".hash
=> 100
irb(main):004:0> "b".hash
=> 101
irb(main):005:0> h = {"a"=>1, "b"=>2}
=> {"a"=>1, "b"=>2}
irb(main):006:0> h.keys
=> ["a", "b"]
irb(main):007:0> h.values
=> [1, 2]
### Now try in different order ###
irb(main):008:0> h = {"b"=>2, "a"=>1}
=> {"a"=>1, "b"=>2}
irb(main):009:0> h.keys
=> ["a", "b"]
irb(main):010:0> h.values
=> [1, 2]

100 comes before 101.

-Charlie