Ruby:行" m = Hash.new {| h,k | h [k] = []}"完成那个" Hash.new"没有按'吨?

时间:2013-11-29 04:13:32

标签: ruby hash rack

在研究this Railscast时,我从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

我的问题是关于第三行。将块{|h,k| h[k] = []}传递给Hash.new的成就是什么?我在IRB中尝试了它,它似乎与常规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

...但是我猜猜那些编写Rack的人比我更了解Ruby。包含该块的原因是什么?

2 个答案:

答案 0 :(得分:11)

它允许您将默认值定义为数组

h = Hash.new { |h, k| h[k] = [] }
h[:a]        # => {:a=>[]}
h[:b] << 123 # => {:a=>[], :b=>[123]}

此处有更多示例:Hash.new

答案 1 :(得分:2)

这将创建默认对象(在这种情况下为[])作为每个键的值。它隐式调用h1 [:a] = [],导致哈希中添加了密钥。

h1 = Hash.new {|h,k| h[k] = []} 
h1[:a] # = []
h1[:a].push(1) # = [1]
h1[:b] # = []
h1 #= {:a=>[1], :b=>[]}

这将返回一个默认对象作为所有键的值。

h1 = Hash.new([])
h1[:a] # = []
h1[:a].push(1) # = [1]
h1[:b] # = [1]
h1 #= {}

这将返回默认对象作为所有键的值。但是不会向哈希添加密钥。

h1 = Hash.new{[]}
h1[:a] # = []
h1[:a].push(1) # = [1]
h1[:b] # = []
h1 #= {}