Hash

Hi

h=Hash.new => {}
h[1] << '1' => ["1"]
h => {} # OK, BUT wouldn't it be nice to have h[1] now?

Opti

Hi

h=Hash.new => {}

That array becomes a default value - not a value stored in the hash. You
want

h = Hash.new { |h,k| h[k] = }

The block gets the hash and the key and stores a new array within the hash

Going back to your example

h=Hash.new => {}

h[1] << '1' => ["1"]

h => {} # OK, BUT wouldn't it be nice to have h[1]

h[1] here returns ['1'] - because the default value of the hash is the
array that you added '1' to.
h[2] h[3] or h[189198120182901] would all return ['1'] because they all
would go to that same default value.

But the hash itself does not store the default value. It returns it and
walks away without storing it.

John

···

On Fri, Jun 3, 2022 at 10:11 PM Die Optimisten <inform@die-optimisten.net> wrote:

It is the same as:

irb(main):001:0> h = Hash.new(0)
=> {}
irb(main):002:0> h[1]
=> 0
irb(main):003:0> h
=> {}

A default value is just returned if the key does not exist in the hash, not
assigned.

Your example takes the returned value and mutates it, that may mud the
waters, but perhaps the 0 example above clarifies.

Even worse. The *same* array reference is returned for every key miss. The
default value is one particular object, the one you passed to Hash.new.
Therefore, this happens:

irb(main):001:0> h = Hash.new()
=> {}
irb(main):002:0> h[1] << 1
=> [1]
irb(main):003:0> h[2] << 1
=> [1, 1]
irb(main):004:0> h[3] << 1
=> [1, 1, 1]

See, same array reference mutated multiple times (and no entry effectively
created in the hash, still).

The idiomatic way to do this like you expect is John's solution.

Thanks Xavier! This motivated me to really #ReadTheDocs :slight_smile: and level up my usage of the Ruby hash.

Best Regards,
Mohit.
2022-6-6 | 8:43 pm.

···

On 2022-6-4 1:42 pm, Xavier Noria wrote:

It is the same as:

    irb(main):001:0> h = Hash.new(0)
    => {}
    irb(main):002:0> h[1]
    => 0
    irb(main):003:0> h
    => {}