Strange, unexpected behavior (disappearing/changing values) when using Hash default value, e.g. Hash.new([])

前端 未结 4 1977
情歌与酒
情歌与酒 2020-11-21 11:31

Consider this code:

h = Hash.new(0)  # New hash pairs will by default have 0 as values
h[1] += 1  #=> {1=>1}
h[2] += 2  #=> {2=>2}
4条回答
  •  借酒劲吻你
    2020-11-21 12:14

    The operator += when applied to those hashes work as expected.

    [1] pry(main)> foo = Hash.new( [] )
    => {}
    [2] pry(main)> foo[1]+=[1]
    => [1]
    [3] pry(main)> foo[2]+=[2]
    => [2]
    [4] pry(main)> foo
    => {1=>[1], 2=>[2]}
    [5] pry(main)> bar = Hash.new { [] }
    => {}
    [6] pry(main)> bar[1]+=[1]
    => [1]
    [7] pry(main)> bar[2]+=[2]
    => [2]
    [8] pry(main)> bar
    => {1=>[1], 2=>[2]}
    

    This may be because foo[bar]+=baz is syntactic sugar for foo[bar]=foo[bar]+baz when foo[bar] on the right hand of = is evaluated it returns the default value object and the + operator will not change it. The left hand is syntactic sugar for the []= method which won't change the default value.

    Note that this doesn't apply to foo[bar]<<=bazas it'll be equivalent to foo[bar]=foo[bar]< and << will change the default value.

    Also, I found no difference between Hash.new{[]} and Hash.new{|hash, key| hash[key]=[];}. At least on ruby 2.1.2 .

提交回复
热议问题