Confusin with Hash default

I was doing some practice and play with Hash default value as written in
the documentation.

h = Hash.new([])
h[:a] << 2
h[:a] << 3
h[:a] # => [2, 3]

Till above is perfect.

h # => {}

Why the Hash h is empty hash here?

h[:b] << 2
h[:b] # => [2, 3, 2]

How h[:b] is [2, 3, 2] instead of only [2] ?

I can answer the second part, but would have to think a bit about the
first:

On 23 June 2013 16:17, Love U Ruby [email protected] wrote:

h # => {}

Why the Hash h is empty hash here?

h[:b] << 2
h[:b] # => [2, 3, 2]

How h[:b] is [2, 3, 2] instead of only [2] ?

Object references.

Try it like this:

ary = []
hsh = Hash.new(ary)
hsh[:x] #=> []

ary << 1
hsh[:x] #=> [1]

Every “default” element of hsh contains a reference to the ary
object. Similarly, in your original example, every default element of
h contained a reference to the unnamed array object.

At a guess as to the first part:

h = Hash.new([])

1. you create an unnamed array object

2. you create a hash object, whose “default value” is a reference to

that array object
h[:a] << 2

3. h has no key :a, so h[:a] returns the default object (the

unnamed array) above

4. you call << 2 on that default object; so the unnamed array now

has one element
h[:a] << 3

5. (as above, now it has two elements)

h[:a] # => [2, 3]

6. h still has no key :a, so h[:a] returns the default object (the

unnamed array) above, which has the two elements you assigned it

h # => {}

7. at no point above did you add an element to h; all you did is

get an element (which didn’t exist, so you always got the default),
so h remains empty

h[:b] << 2

8. like above: h has no key :b, so h[:b] returns the default object

9. you call << 2 on that object, so now it has 3 elements

h[:b] # => [2, 3, 2]

10. h still has no key :b, so h[:b] returns the default object,

which is an array with 3 elements

Humm… Great catch… Thanks for your help ;

h = {}
h[:a] = 2
h # => {:a=>2}

h = Hash.new([])
h[:a] = h[:a] << 2
h # => {:a=>[2]}

Thanks to all for your extraordinary helps… :))

Am 23.06.2013 08:17, schrieb Love U Ruby:

h # => {}

Why the Hash h is empty hash here?

h[:b] << 2
h[:b] # => [2, 3, 2]

How h[:b] is [2, 3, 2] instead of only [2] ?

The documentation is very specific about the difference between
Hash.new() and Hash.new {}, providing in the first case a single
default object, whereas in the second case a fresh object is returned.
You should study the given examples.

On 2013-06-23, at 3:33 AM, Love U Ruby [email protected] wrote:


Posted via http://www.ruby-forum.com/.

Watch out using Hash.new([]) - you have to be aware of what it does. It
sets the hash’s default object, and there is only one of them per hash,
and you might not see the expected list of keys because you are updating
the Hash’s default object:

ratdog:tmp mike$ pry
[1] pry(main)> h = Hash.new([])
=> {}
[2] pry(main)> h[:a] << 2
=> [2]
[3] pry(main)> h[:b] << 3
=> [2, 3]
[4] pry(main)> h[:a].object_id
=> 70203880282800
[5] pry(main)> h[:b].object_id
=> 70203880282800
[6] pry(main)> h.default
=> [2, 3]
[7] pry(main)> h.keys
=> []
[8] pry(main)> h
=> {}

If you specify a block then you can get a new object for each time you
need a default, and get the kind of behaviour most people expect:

[9] pry(main)> h2 = Hash.new { |h, k| h[k] = [] }
=> {}
[10] pry(main)> h2[:a] << 2
=> [2]
[11] pry(main)> h2[:b] << 3
=> [3]
[12] pry(main)> h2[:a].object_id
=> 70203901671420
[13] pry(main)> h2[:b].object_id
=> 70203903870340
[14] pry(main)> h2
=> {:a=>[2], :b=>[3]}

Hope this helps,

Mike

Mike S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.