From: Robert Klemme Date: 2011-02-23T17:25:41+09:00 Subject: Re: Ruby Hash Keys and Related Questions On Wed, Feb 23, 2011 at 7:42 AM, Terry Michaels wrote: > I'm still a bit new to Ruby, so humor me a bit. But I discovered today > (through trial and error) that not only can Strings, numbers, and > symbols be keys for hashes, but also any object, or even a class name! > Ruby is the first language I've used in which I would have even thought > to try that, let alone it actually working: > Anyway, this raised a few related questions in my mind: > > 1. If the "key" taken by hash[key]= can be any object, and the key still > works even after it is aliased to another variable, does that mean that > the "key" is just a reference? Yes, in Ruby you always only ever see references. This means, that if you modify an instance which is used in a Hash as key the Hash likely needs updating since the hash code of the key usually also changes (see Hash#rehash). > 2. If I pass in a number, say an Integer, as a key, does Ruby actually > use the Integer? Or does it use a reference to an Integer object? > (Numbers are objects too, right?) Yes, everything is an object in Ruby. There are some optimizations internally but as a user of the language you do not see them. Anything, and I mean _anything_, in Ruby is an object and can be referenced by any variable. > 3. If I am allowed to pass in a class as a key, does that mean that > classes are objects too? If not, what exactly is being stored as the > key? Yes, classes are objects, too. Classes are instances of class Class: irb(main):002:0> String.class => Class irb(main):003:0> String.class.ancestors => [Class, Module, Object, Kernel] irb(main):004:0> String.kind_of? Object => true There is a tad of recursion involved but you should just accept it and not think about it too much. Otherwise serious brain damage could be the consequence. :-) > 4. When I use irb, and a line returns an object, irb shows me the > object's hexadecimal reference address (or at least, that's what it > looks like). Is there a method one can call on an object to get that > reference when one is not in irb? Just curious. No, IRB shows the result of obj.inspect. The default implementation returns something which is related to #object_id which in turn is derived from the address (I forgot the details): irb(main):010:0> o=Object.new => # irb(main):011:0> o.object_id.to_s 16 => "3ffb962e" irb(main):012:0> 0x7ff72c5c / 0x3ffb962e => 2 Anyway, since you cannot access memory directly from Ruby it's worthless to know the memory address. And in other Ruby implementations (e.g. JRuby) that memory address may even change. Forget C (until you write your first Ruby extension). Ah, and one note: Ruby's Hash will apply special treatment to String keys if they are not frozen. In this case the key is copied so you can safely modify the key you passed: irb(main):015:0> h={} => {} irb(main):016:0> k="foo" => "foo" irb(main):017:0> h[k]="x" => "x" irb(main):018:0> h => {"foo"=>"x"} irb(main):019:0> k << "_modified" => "foo_modified" irb(main):020:0> k => "foo_modified" irb(main):021:0> h => {"foo"=>"x"} irb(main):022:0> k.object_id => 1073420300 irb(main):023:0> h.each {|k,v| puts k, k.object_id} foo 1073420320 => {"foo"=>"x"} If you know you do not need to modify a String key afterwards you can gain a few CPU cycles by freezing the String. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/