Thursday, September 21, 2006

Hashes, Defaults, and Objects

I just read Ruby Hashes of Arbitrary Depth by Duane Johnson (another UtahValley.rb/BYU-RUG Rubyist), and thought it was worth pointing out. The funny part (to me) was that he and I had spent a bit of time last night scratching our heads over the problem that he describes.

One thing I wish he'd mentioned in his post is an important fact that slipped both our minds and made the problem a bit more mysterious. Let me show you what I mean:


irb(main):001:0> foo = Hash.new({})
=> {}
irb(main):002:0> foo[:bar][:baz] = "wokka"
=> "wokka"
irb(main):003:0> foo
=> {}
irb(main):004:0> foo[:bar]
=> {:baz=>"wokka"}
irb(main):005:0> foo["what's this"]
=> {:baz=>"wokka"}

The thing we forgot, was that when you set a default value for a Hash, you're setting it to a specific object. So foo[:bar][:baz] = "wokka" isn't really creating a Hash called :bar with a key-value pair of :baz => "wokka". It's adding :baz => "wokka" to the default object. You can do this though:


 irb(main):006:0> foo[:pinky] = "blinky"
=> "blinky"
irb(main):007:0> foo
=> {:pinky=>"blinky"}
irb(main):008:0> foo[:possum]
=> {:baz=>"wokka"}
irb(main):009:0> quit
Any key value pairs you explictly create will be there just like you expect.

Just something to remember.

No comments: