While studying this Railscast I came across the following bit of source code from Rack:
def self.middleware
@middleware ||= begin
m = Hash.new {|h,k| h[k] = []}
m["deployment"].concat [
[Rack::ContentLength],
[Rack::Chunked],
logging_middleware
]
m["development"].concat m["deployment"] + [[Rack::ShowExceptions], [Rack::Lint]]
m
end
end
My question is about the third line. What does passing the block {|h,k| h[k] = []}
to Hash.new
accomplish? I tried it in IRB and it doesn't seem to do anything different from a regular Hash.new
:
2.0.0p247 :003 > m1 = Hash.new
=> {}
2.0.0p247 :004 > m2 = Hash.new{|h,k| h[k] = []}
=> {}
2.0.0p247 :005 > m1 == m2
=> true
... but I'm going to guess that the guys who wrote Rack know more about Ruby than I do. What's the reasoning behind including that block?
A Hash is a dictionary-like collection of unique keys and their values. Also called associative arrays, they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type. Hashes enumerate their values in the order that the corresponding keys were inserted.
In Ruby, Hash is a collection of unique keys and their values. Hash is like an Array, except the indexing is done with the help of arbitrary keys of any object type. In Hash, the order of returning keys and their value by various iterators is arbitrary and will generally not be in the insertion order.
In Ruby, the values in a hash can be accessed using bracket notation. After the hash name, type the key in square brackets in order to access the value.
Typically when an element is passed into a hash with no matching key, the hash returns nil .
It allows you to define default value as an array
h = Hash.new { |h, k| h[k] = [] }
h[:a] # => {:a=>[]}
h[:b] << 123 # => {:a=>[], :b=>[123]}
More examples are here: Hash.new
This creates default object ([] in this case) as value for every key. It calls h1[:a] = [] implicitly resulting in addition of key in the hash.
h1 = Hash.new {|h,k| h[k] = []}
h1[:a] # = []
h1[:a].push(1) # = [1]
h1[:b] # = []
h1 #= {:a=>[1], :b=>[]}
This returns a single default object as value for all keys.
h1 = Hash.new([])
h1[:a] # = []
h1[:a].push(1) # = [1]
h1[:b] # = [1]
h1 #= {}
This returns default object as value for all keys. But does not add key to the hash.
h1 = Hash.new{[]}
h1[:a] # = []
h1[:a].push(1) # = [1]
h1[:b] # = []
h1 #= {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With