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]` ?

···

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

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

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]` ?

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

···

On 23 June 2013 16:17, Love U Ruby <lists@ruby-forum.com> wrote:

--
  Matthew Kerwin, B.Sc (CompSci) (Hons)
  http://matthew.kerwin.net.au/

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]}

···

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

Thanks to all for your extraordinary helps... :))

···

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

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.

···

Am 23.06.2013 08:17, schrieb Love U Ruby:

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]` ?

--
<https://github.com/stomar/&gt;

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

···

On 2013-06-23, at 3:33 AM, Love U Ruby <lists@ruby-forum.com> wrote:

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]}

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

--

Mike Stok <mike@stok.ca>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.