Monday, May 4, 2009

Ruby Hashes and Default Values

I’m currently experimenting with MacJournal, so this will be a short entry to test the publishing functionality and blogger integration.

Ruby’s Hash/Associative array has some great ways to default values. All of this is done in the Hash constructor:

First, we create a new hash (h) that returns nil for the default value. This is done by passing nothing to the Hash constructor.
>> h = Hash.new
=> {}
>> h[5]
=> nil
>> h["eggs"]
=> nil

No surprises here. Now we need to default a Hash value. We’ll start by creating the Hash and setting the default value to an empty list [].
>> h = Hash.new []
=> {}
>> h[5]
=> []
>> h["eggs"]
=> []

Now the ‘nugget’.
>> h
=> {}

h is STILL empty. The hash only provides us the default value, it does not insert it back in the Hash for us.

‘Nugget’ 2.
The default value that is returned is NOT cloned.
>> h[5] << "spam"
=> ["spam"]
>> h["eggs"]
=> ["spam"]

Our default value has changed! We can also demonstrate this with a string object:
>> h = Hash.new "spam"
=> {}
>> h["eggs"]
=> "spam"
>> h["eggs"] << " is yummy!"
=> "spam is yummy!"
>> h["shampoo"]
=> "spam is yummy!"

You can force a Hash to create a new default value every time if you pass it a block in the constructor. The blocks parameters are the Hash itself and the key for which a default value needs to be created. This form is by far the most flexible as the default value can even be customized for the key, it doesn’t have to be the same one every time.
>> h = Hash.new {|h, k| h[k] = []}
=> {}
>> h[5]
=> []
>> h["eggs"]
=> []
>> h
=> {5=>[], "eggs"=>[]}
>> h[5] << "spam"
=> ["spam"]
>> h["eggs"]
=> []
>> h
=> {5=>["spam"], "eggs"=>[]}

Hope that saves you the 10 minutes it took me to figure this out. It is also detailed in the ruby doc for Hash. Guess I get the RTFRD award for the evening.

No comments: