0

I'm trying to have a hash whose value is an array.

I use the new method with an empty array as the default value, so it was my assumption that @hash[a][0] = b would first get an empty array (from @hash[a]) and then assign the 0 index value to b.

For some reason, the hash shows as empty, with size zero, even though the items can be accessed as expected. Can anyone explain why?

Another person has pointed out that it will work if I use @hash = {}, but this requires instantiating the empty array for each key I add, which is an inconvenience, and I'm curious how the value can be accessed despite the size remaining zero.

class Test
  def initialize
    @hash = Hash.new []
  end

  def run
    a = Object.new
    b = Object.new
    @hash[a][0] = b

    puts @hash # outputs {}
    puts @hash.size # outputs 0
    puts @hash[a].inspect # outputs [#<Object:0x00007fe2bb80caa0>]
    puts @hash[a][0].inspect # outputs #<Object:0x00007fe2bb80caa0>
  end
end

test = Test.new
test.run
sawa
  • 165,429
  • 45
  • 277
  • 381
b-wick
  • 33
  • 1
  • 5
  • 1
    "but this requires instantiating the empty array for each key I add" - not necessarily. Use the third form of `Hash.new` (which you can find in the documentation) – Sergio Tulentsev May 10 '18 at 09:37

1 Answers1

2

After a little assistance on a Slack channel, I now understand.

When you call [] with a key that doesn't exist, it'll return a new array instance. You are then calling [0] on that new array and that value is returned, but that new array isn't actually assigned to anything, so it disappears and you see no new key/val on your hash.

Every time you call this, it returns the same array instance, and hence why I was able to access the values I had assigned even though the hash didn't show them as being saved.

b-wick
  • 33
  • 1
  • 5
  • Yes, that's a common rookie gotcha with hash and its default value. – Sergio Tulentsev May 10 '18 at 09:31
  • 3
    "a new array instance", "it disappears" - careful with the wording. It's the same array instance, which is certainly not disappearing anywhere. It remains referenced by the hash as a default value. – Sergio Tulentsev May 10 '18 at 09:34