Thu May 2014

Ruby's `Hash#new`

method accepts an optional parameter which is
returned when you try to access a key that does not exist in the hash (the default is nil). For example:

```
h = Hash.new('bar') #=> {}
puts h[:foo] #=> 'bar'
```

```
h = Hash.new('bar') #=> {}
puts h[:foo] #=> 'bar'
```

While the first example may not very useful, `Hash#new`

also accepts a
block that will be called with the hash object and the key whenever you try to access
a key that does not exist in the hash, for example:

```
upcase = Hash.new { |hash, k| "#{k}".upcase } #=> {}
upcase['foo'] #=> "FOO"
```

```
upcase = Hash.new { |hash, k| "#{k}".upcase } #=> {}
upcase['foo'] #=> "FOO"
```

You can also modify the hash within the callback. Here's a more useful example where we create a memoized version of the fibonacci sequence:

```
fibonacci = Hash.new do |hash, k|
case k
when 0
hash[k] = 0
when 1, 2
hash[k] = 1
else
hash[k] = hash[k-1] + hash[k-2]
end
end
```

```
fibonacci = Hash.new do |hash, k|
case k
when 0
hash[k] = 0
when 1, 2
hash[k] = 1
else
hash[k] = hash[k-1] + hash[k-2]
end
end
```

Using this hash, whenever we compute the nth fibonacci number all the n - 1 fibonacci numbers will be cached in the hash, significantly reducing the number of recursive calls needed to compute the next fibonacci number.

```
puts fibonacci[5] #=> 5
puts fibonacci #{2=>1, 1=>1, 3=>2, 4=>3, 5=>5}
```

```
puts fibonacci[5] #=> 5
puts fibonacci #{2=>1, 1=>1, 3=>2, 4=>3, 5=>5}
```