Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: What does the line "m = Hash.new {|h,k| h[k] = []}" accomplish that "Hash.new" doesn't?

Tags:

ruby

hash

rack

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?

like image 350
GMA Avatar asked Nov 29 '13 04:11

GMA


People also ask

What does hash do in Ruby?

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.

What is new hash Ruby?

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.

How do I get the hash value in Ruby?

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.

What is returned if you pass a key that doesnt exist into a hash?

Typically when an element is passed into a hash with no matching key, the hash returns nil .


2 Answers

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

like image 197
ncwrch Avatar answered Nov 15 '22 10:11

ncwrch


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 #= {}
like image 29
Bhuvna Prabhu Avatar answered Nov 15 '22 11:11

Bhuvna Prabhu