Hash & keys...

Discussion in 'Ruby' started by Sébastien Wautelet, Oct 13, 2006.

  1. I'm having some trouble understanding how hashes work in Ruby. Consider
    the following test :

    irb(main):002:0> v=Vector[4,5]
    => Vector[4, 5]
    irb(main):003:0> v2=Vector[4,5]
    => Vector[4, 5]
    irb(main):004:0> v==v2
    => true
    irb(main):005:0> v.hash
    => 17
    irb(main):006:0> v2.hash
    => 17
    irb(main):007:0> h=Hash.new
    => {}
    irb(main):008:0> h[v]="whatever is in (4,5)"
    => "whatever is in (4,5)"
    irb(main):009:0> h[v2]
    => nil

    I'd have expected h[v2] => "whatever is in (4,5)", since v==v2 and both
    have the same hash value... what am I doing wrong?

    --
    Posted via http://www.ruby-forum.com/.
     
    Sébastien Wautelet, Oct 13, 2006
    #1
    1. Advertising

  2. Sébastien Wautelet wrote:
    > I'm having some trouble understanding how hashes work in Ruby. Consider
    > the following test :
    >
    > irb(main):002:0> v=Vector[4,5]
    > => Vector[4, 5]
    > irb(main):003:0> v2=Vector[4,5]
    > => Vector[4, 5]
    > irb(main):004:0> v==v2
    > => true
    > irb(main):005:0> v.hash
    > => 17
    > irb(main):006:0> v2.hash
    > => 17
    > irb(main):007:0> h=Hash.new
    > => {}
    > irb(main):008:0> h[v]="whatever is in (4,5)"
    > => "whatever is in (4,5)"
    > irb(main):009:0> h[v2]
    > => nil
    >
    > I'd have expected h[v2] => "whatever is in (4,5)", since v==v2 and both
    > have the same hash value... what am I doing wrong?
    >
    >

    It's not enough that they have the same hash value or that obj1 == obj2.
    For the purposes of Hash, two objects are the same if obj1.eql?(obj2).
    Does v1.eql?(v2)?
     
    Timothy Hunter, Oct 13, 2006
    #2
    1. Advertising

  3. Sébastien Wautelet

    Daniel Waite Guest

    Sébastien Wautelet wrote:
    > I'd have expected h[v2] => "whatever is in (4,5)", since v==v2 and both
    > have the same hash value... what am I doing wrong?


    Hash keys can be any object. So your hash, h, has one key, the object v.

    Take another hash real quick, we'll call it hash.

    hash = Hash.new

    hash['rabbit'] = 'cute' # 'cute'
    hash['blue'] # nil

    The value for any hash key not defined is nil (unless you explicitly
    tell the hash during instantiation to use another value).

    So just because you're using the value of v as a key in your hash, does
    not mean that v2 is automatically another key in your hash.

    --
    Posted via http://www.ruby-forum.com/.
     
    Daniel Waite, Oct 13, 2006
    #3
  4. Sébastien Wautelet

    Daniel Waite Guest

    I think you're getting hung up on this part:

    Sébastien Wautelet wrote:
    > irb(main):004:0> v==v2
    > => true


    Yes, v and v2 are equal. But that is irrelevant with regards to your
    hash.

    Now, if you had to objects that were identical (not equal, but
    identical) then it would work:

    s1 = 'string'
    s2 = s1

    h = Hash.new

    h[s1] # 'string'
    h[s2] # 'string'

    s1.upcase!

    h[s2] # 'STRING'
    h[s1] # 'STRING'

    Hope that helps.

    --
    Posted via http://www.ruby-forum.com/.
     
    Daniel Waite, Oct 13, 2006
    #4
  5. Timothy Hunter wrote:
    > S=C3=A9bastien Wautelet wrote:
    >> I'm having some trouble understanding how hashes work in Ruby.=20
    >> Consider the following test :
    >>
    >> irb(main):002:0> v=3DVector[4,5]
    >> =3D> Vector[4, 5]
    >> irb(main):003:0> v2=3DVector[4,5]
    >> =3D> Vector[4, 5]
    >> irb(main):004:0> v=3D=3Dv2
    >> =3D> true
    >> irb(main):005:0> v.hash
    >> =3D> 17
    >> irb(main):006:0> v2.hash
    >> =3D> 17
    >> irb(main):007:0> h=3DHash.new
    >> =3D> {}
    >> irb(main):008:0> h[v]=3D"whatever is in (4,5)"
    >> =3D> "whatever is in (4,5)"
    >> irb(main):009:0> h[v2]
    >> =3D> nil
    >>
    >> I'd have expected h[v2] =3D> "whatever is in (4,5)", since v=3D=3Dv2 a=

    nd=20
    >> both have the same hash value... what am I doing wrong?
    >>
    >> =20

    > It's not enough that they have the same hash value or that obj1 =3D=3D =


    > obj2. For the purposes of Hash, two objects are the same if=20
    > obj1.eql?(obj2). Does v1.eql?(v2)?
    >
    >

    Testing reveals that they don't. but that strikes me as a bug in the=20
    Vector class. It violates the guidelines given in the PickAxe book=20
    (bottom of page 568), and more importantly, it violates common=20
    intuition. If two vectors that are created in exactly the same manner=20
    aren't eql?, they're useless for use as hash keys. I'd say file a bug=20
    report, or at least a problem, on this one.

    Cheers,
    Ken
     
    Kenneth McDonald, Oct 13, 2006
    #5
  6. Sébastien Wautelet

    Phrogz Guest

    Daniel Waite wrote:
    > I think you're getting hung up on this part:
    >
    > Sébastien Wautelet wrote:
    > > irb(main):004:0> v==v2
    > > => true

    >
    > Yes, v and v2 are equal. But that is irrelevant with regards to your
    > hash.
    >
    > Now, if you had to objects that were identical (not equal, but
    > identical) then it would work:


    I think it is relevant, given that the Vector class is designed to be
    immutable. I would agree that the Vector class should probably define
    #eql? as an alias for #==.
     
    Phrogz, Oct 13, 2006
    #6
  7. On 10/13/06, Phrogz <> wrote:

    > I think it is relevant, given that the Vector class is designed to be
    > immutable. I would agree that the Vector class should probably define
    > #eql? as an alias for #==.


    It appears to be a typo in Matrix.rb - This is in ruby1.8.4:

    class Vector
    ...
    #
    # Returns +true+ iff the two vectors have the same elements in the same order.
    #
    def ==(other)
    return false unless Vector === other

    other.compare_by(@elements)
    end
    alias eqn? ==
    ~~~

    And Vector seems to be the only implementor of eqn?

    rick@frodo:~/ruby-1.8.4$ ri eqn
    ------------------------------------------------------------ Vector#eqn?
    eqn?(other)
    ------------------------------------------------------------------------
    Alias for #==

    And it's not yet fixed in 1.9
    rick@frodo:~/ruby-1.8.4$ grep eqn /public/rubysource/ruby1.9/ruby/lib/matrix.rb
    alias eqn? ==



    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
     
    Rick DeNatale, Oct 13, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    591
    red floyd
    Nov 10, 2011
  2. Xeno Campanoli
    Replies:
    16
    Views:
    287
    Martin DeMello
    Aug 25, 2005
  3. Alex Fenton

    Hash#values and Hash#keys order

    Alex Fenton, Apr 7, 2006, in forum: Ruby
    Replies:
    1
    Views:
    162
    George Ogata
    Apr 15, 2006
  4. Mage

    hash.keys and hash.values

    Mage, Aug 13, 2006, in forum: Ruby
    Replies:
    14
    Views:
    194
  5. Ronald Fischer

    Hash#keys, Hash#values order question

    Ronald Fischer, Aug 23, 2007, in forum: Ruby
    Replies:
    0
    Views:
    172
    Ronald Fischer
    Aug 23, 2007
Loading...

Share This Page