# Hash.new(confusion)

**URL:** <https://rubytalk.org/t/hash-new-confusion/20459>\
**Category:** ruby-talk\
**Created:** [29 August 2005 04:16 UTC](https://rubytalk.org/t/hash-new-confusion/20459 "2005-08-29T04:16:33Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [29 August 2005 04:16 UTC](https://rubytalk.org/t/hash-new-confusion/20459/1 "2005-08-29T04:16:33Z")

</div>

irb(main):006:0\> def r  
irb(main):007:1\> @r ||= Hash.new({})  
irb(main):008:1\> end  
=\> nil  
irb(main):009:0\> r[:a]  
=\> {}  
irb(main):010:0\> r[:b][:c] = 10  
=\> 10  
irb(main):011:0\> r  
=\> {}  
irb(main):012:0\> r[:b]  
=\> {:c=\>10}  
irb(main):013:0\>

Please explain how r is empty but r[:b] exists. Thank You.

T.

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [29 August 2005 04:49 UTC](https://rubytalk.org/t/hash-new-confusion/20459/2 "2005-08-29T04:49:58Z")

</div>

Trans wrote:

> irb(main):006:0\> def r  
> irb(main):007:1\> @r ||= Hash.new({})  
> irb(main):008:1\> end  
> =\> nil  
> irb(main):009:0\> r[:a]  
> =\> {}  
> irb(main):010:0\> r[:b][:c] = 10  
> =\> 10  
> irb(main):011:0\> r  
> =\> {}  
> irb(main):012:0\> r[:b]  
> =\> {:c=\>10}  
> irb(main):013:0\>
> 
> Please explain how r is empty but r[:b] exists. Thank You.
> 
> T.

Try

p r.default

and you'll see what's going on.

> **···**
>
> --  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

---

<div class="post-metadata">

**Author:** ![Gennady1](https://avatars.discourse-cdn.com/v4/letter/g/a4c791/32.png) [@Gennady1](https://rubytalk.org/u/Gennady1)\
**Post date:** [29 August 2005 04:52 UTC](https://rubytalk.org/t/hash-new-confusion/20459/3 "2005-08-29T04:52:36Z")

</div>

If you specify a parameter for Hash.new the SAME object will be used for any default value (see documentation). If you modify it, it will be modified for all default values afterwards. Try to see what the value will be returned for r[:a] if you do it again. I bet it will be {:c =\> 10}. As well as for r[:c], r[10] and so on.

Gennady.

> **···**
>
> On Aug 28, 2005, at 21:16, Trans wrote:
> 
> > irb(main):006:0\> def r  
> > irb(main):007:1\> @r ||= Hash.new({})  
> > irb(main):008:1\> end  
> > =\> nil  
> > irb(main):009:0\> r[:a]  
> > =\> {}  
> > irb(main):010:0\> r[:b][:c] = 10  
> > =\> 10  
> > irb(main):011:0\> r  
> > =\> {}  
> > irb(main):012:0\> r[:b]  
> > =\> {:c=\>10}  
> > irb(main):013:0\>
> > 
> > Please explain how r is empty but r[:b] exists. Thank You.
> > 
> > T.

---

<div class="post-metadata">

**Author:** ![Mitch](https://avatars.discourse-cdn.com/v4/letter/m/dec6dc/32.png) [@Mitch](https://rubytalk.org/u/Mitch)\
**Post date:** [29 August 2005 05:06 UTC](https://rubytalk.org/t/hash-new-confusion/20459/4 "2005-08-29T05:06:07Z")

</div>

r is independent of r[:b]. r[:b] is a hash with a value containing another hash/key value.

ie {:b =\> {:c =\> 10}} NOT {:b =\> 10, :c = 10}. If I understand your confusion correctly.

irb(main):001:0\> def r  
irb(main):002:1\> @r ||= Hash.new({})  
irb(main):003:1\> end  
=\> nil  
irb(main):004:0\> r[:a]  
=\> {}  
irb(main):005:0\> r.empty?  
=\> true  
irb(main):006:0\> r[:a] = 1  
=\> 1  
irb(main):007:0\> r.empty?  
=\> false  
irb(main):008:0\> r[:b][:c] = 10  
=\> 10  
irb(main):009:0\> r  
=\> {:a=\>1}  
irb(main):010:0\> r[:b]  
=\> {:c=\>10}  
irb(main):011:0\> (r[:b])[:c]  
=\> 10  
irb(main):012:0\> r[:a]  
=\> 1  
irb(main):013:0\> r.size  
=\> 1  
irb(main):014:0\> r[:b].size  
=\> 1  
irb(main):015:0\> r[:b][:d] = 300000  
=\> 300000  
irb(main):016:0\> r[:b].size  
=\> 2  
irb(main):018:0\> r  
=\> {:a=\>1}  
irb(main):019:0\> r[:b]  
=\> {:d=\>300000, :c=\>10}

Or did I completely miss your point?

Mitch

> **···**
>
> On Aug 28, 2005, at 11:16 PM, Trans wrote:
> 
> > irb(main):006:0\> def r  
> > irb(main):007:1\> @r ||= Hash.new({})  
> > irb(main):008:1\> end  
> > =\> nil  
> > irb(main):009:0\> r[:a]  
> > =\> {}  
> > irb(main):010:0\> r[:b][:c] = 10  
> > =\> 10  
> > irb(main):011:0\> r  
> > =\> {}  
> > irb(main):012:0\> r[:b]  
> > =\> {:c=\>10}  
> > irb(main):013:0\>
> > 
> > Please explain how r is empty but r[:b] exists. Thank You.
> > 
> > T.

---

<div class="post-metadata">

**Author:** ![Dave\_Burt2](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/dave_burt2/32/2036_2.png) [@Dave\_Burt2](https://rubytalk.org/u/Dave_Burt2)\
**Post date:** [29 August 2005 05:16 UTC](https://rubytalk.org/t/hash-new-confusion/20459/5 "2005-08-29T05:16:22Z")

</div>

transfire@gmail.com wrote:

> ...  
> Please explain how r is empty but r[:b] exists. Thank You.

# To summarize:  
h = Hash.new({})  
h[1][2] = 3  
h #=\> {}  
h.default #=\> {2=\>3}

So you've added to the default object. It might be helpful to note another  
wrong way to do this:  
h = Hash.new { {} }  
h[1][2] = 3  
h #=\> {}  
h.default #=\> {}

Different, because default now returns a new hash every time.

But, to answer the implied question, "what is the code that will do what I  
intend?" there are a few ways to do this:

# Just one level of magic new hashes  
h = Hash.new {|hash, key| hash[key] = {} }  
h[1][2] = 3  
h #=\> {1=\>{2=\>3}}  
h[1][2][3] = 4 # Error (calling = on nil)

# Auto-vivifying hash: using proc  
auto\_vivivy\_hash = proc {|hash, key| hash[key] = Hash.new  
&auto\_vivivy\_hash }  
h = Hash.new &auto\_vivify\_hash  
h[1][2][3] = 4 #=\> {1=\>{2=\>{3=\>4}}}

# Auto-vivifying hash: using Hash subclass  
class X \< Hash  
&nbsp;&nbsp;def default(key = nil)  
&nbsp;&nbsp;&nbsp;&nbsp;self[key] = self.class.new  
&nbsp;&nbsp;end  
end  
h = X.new #=\> {}  
h[1][2][3] = 4  
h #=\> {1=\>{2=\>{3=\>4}}}

Cheers,  
Dave

---

<div class="post-metadata">

**Author:** ![David\_A\_Black3](https://avatars.discourse-cdn.com/v4/letter/d/6a8cbe/32.png) [@David\_A\_Black3](https://rubytalk.org/u/David_A_Black3)\
**Post date:** [29 August 2005 11:47 UTC](https://rubytalk.org/t/hash-new-confusion/20459/6 "2005-08-29T11:47:03Z")

</div>

Hi --

> **···**
>
> On Mon, 29 Aug 2005, Trans wrote:
> 
> > irb(main):006:0\> def r  
> > irb(main):007:1\> @r ||= Hash.new({})  
> > irb(main):008:1\> end  
> > =\> nil  
> > irb(main):009:0\> r[:a]  
> > =\> {}  
> > irb(main):010:0\> r[:b][:c] = 10  
> > =\> 10  
> > irb(main):011:0\> r  
> > =\> {}  
> > irb(main):012:0\> r[:b]  
> > =\> {:c=\>10}  
> > irb(main):013:0\>
> > 
> > Please explain how r is empty but r[:b] exists. Thank You.
> 
> r[:b] doesn't exist, so instead, you get the hash's default value  
> (which is what is returned for non-existent keys).
> 
> David
> 
> --  
> David A. Black  
> dblack@wobblini.net

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [29 August 2005 12:01 UTC](https://rubytalk.org/t/hash-new-confusion/20459/7 "2005-08-29T12:01:23Z")

</div>

Ahhhh, Now I \_finally\_understand. It's quite subtle.

Thank You All!

T.
