# Hash of hash?

**URL:** <https://www.ruby-forum.com/t/hash-of-hash/170605>\
**Category:** Ruby\
**Created:** [June 19, 2009, 4:08pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605 "2009-06-19T16:08:05Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 4:08pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/1 "2009-06-19T16:08:05Z")

</div>

hi,

I am totally new to Ruby and am trying to code a hash of a hash.  
Somehow I always get a syntax error, but am unable to resolve it.

This is what I have:

File 1:  
class Hashhash  
def initialize  
@dt = { 2 =\> {2 =\> “H”, 3 =\> “C”},  
3 =\> {2 =\> “H”, 9 =\> “Dh”},  
“T” =\> {2 =\> “C”, 9 =\> “S”}  
}

```
 return @dt

```

end  
end

File 2:  
require ‘Hashhash’

ah = Hashhash.new

out = ah[“T”][9]

p out

I always get this error:  
test.rb:5: undefined method `[]’ for #Hashhash:0x2bd2e30  
(NoMethodError)

But when I try to code something in irb it works:  
irb(main):006:0\* dt = { 2 =\> {2 =\> “H”, 3 =\> “C”}}  
=\> {2=\>{2=\>“H”, 3=\>“C”}}  
irb(main):007:0\> puts dt[2][2]  
H  
=\> nil

What am I doing wrong??

Thanks in advance

---

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 4:30pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/2 "2009-06-19T16:30:51Z")

</div>

Jeroen L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> class Hashhash  
> …  
> end
> 
> out = ah[“T”][9]  
> …  
> test.rb:5: undefined method `[]’ for #Hashhash:0x2bd2e30

Hi Jeroen,

I think you have to explicitly define a [] method for your class  
(and a []= method, if you want to write values with this syntax too).

Flo

---

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 4:34pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/3 "2009-06-19T16:34:28Z")

</div>

On Friday 19 June 2009, Jeroen L. wrote:

> | @dt = { 2 =\> {2 =\> “H”, 3 =\> “C”},  
> |  
> |But when I try to code something in irb it works:  
> |irb(main):006:0\* dt = { 2 =\> {2 =\> “H”, 3 =\> “C”}}  
> |=\> {2=\>{2=\>“H”, 3=\>“C”}}  
> |irb(main):007:0\> puts dt[2][2]  
> |H  
> |=\> nil  
> |  
> |What am I doing wrong??  
> |  
> |Thanks in advance

First of all, what you get is not a syntax error (which would have  
produced an  
error message like: syntax error, …). The error you see is caused by  
calling a method on an object for which it isn’t defined.

The problem is that when you call the new method of a class (in your  
case,  
Hashhash.new), you don’t get the value returned by initialize, but the  
object  
created by new. This means that ah doesn’t contain a hash, but a  
Hashhash,  
which doesn’t have a [] method.

You have several options on how to do what you want. Depending on what  
exactly  
you need, I think the easiest ones are:

- define an [] method for the Hashhash class. This way, the code you  
wrote  
will work exactly as you meant. Defining such a method is easy. Inside  
the  
definition of the Hashhash class, do:

Calling this method will return the hash stored in @dt under key. Since  
this  
is a hash, you’ll be able to retrieve the value corresponding to the key  
2

- define a method for the Hashhash class which returns the instance  
variable  
@dt and use that to access the elements. To define a method which only  
returns  
the value of an instance variable, you can use the attr\_reader class  
method:

Then, you can write

ha = Hashhash.new

ha.dt[2][2]

- Do not use the Hashhash class and use a simple hash of hashes:

As for the reason it works in irb… well, from what you show us, you  
aren’t  
using the same code you used in the script. At least, in this case dt  
isn’t an  
instance variable (since it doesn’t start with @).

I hope this helps

Stefano

---

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 4:36pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/4 "2009-06-19T16:36:55Z")

</div>

2009/6/19 Florian W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I think you have to explicitly define a [] method for your class  
> (and a []= method, if you want to write values with this syntax too).

Alternatively Jeroen can simply create a Hash with a default\_proc  
which will recursively insert Hashes:

irb(main):001:0\> ha = Hash.new {|h,k| h[k] = Hash.new(&h.default\_proc)}  
=\> {}  
irb(main):002:0\> ha[1][2][3]  
=\> {}  
irb(main):003:0\> ha[1][2][3]=123  
=\> 123  
irb(main):004:0\> ha  
=\> {1=\>{2=\>{3=\>123}}}  
irb(main):005:0\>

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 4:46pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/5 "2009-06-19T16:46:25Z")

</div>

Hi,

Am Freitag, 19. Jun 2009, 23:08:12 +0900 schrieb Jeroen L.:

> class Hashhash  
> def initialize  
> @dt = { 2 =\> {2 =\> “H”, 3 =\> “C”},  
> 3 =\> {2 =\> “H”, 9 =\> “Dh”},  
> “T” =\> {2 =\> “C”, 9 =\> “S”}  
> }  
> return @dt  
> end  
> end

def [] key ; @dt[key] ; end

You don’t need to return anything from `initialize' because its return value is discarded and the invoking`new’ method always  
returns the created object. Btw you don’t need to return anything  
rom assigment methods `member=’ either.

Bertram

---

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 5:42pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/6 "2009-06-19T17:42:43Z")

</div>

Thanks all for the replies, very clear.

I think I will implement an accessor to the hash, I come from a Perl  
world and would build the hash in a seperate routine (to hide the  
initialisation) that returns a reference to the hash.

Would it be possible to make Hashhash inherit from Hash (by using \<  
Hash) and be able to use the [][] operator immediately in a way?

---

<div class="post-metadata">

**Author:** ![wcool](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/b9e5f3/32.png) [@wcool](https://www.ruby-forum.com/u/wcool)\
**Post date:** [June 19, 2009, 6:01pm UTC](https://www.ruby-forum.com/t/hash-of-hash/170605/7 "2009-06-19T18:01:45Z")

</div>

On 19.06.2009 17:42, Jeroen L. wrote:

> Thanks all for the replies, very clear.
> 
> I think I will implement an accessor to the hash, I come from a Perl  
> world and would build the hash in a seperate routine (to hide the  
> initialisation) that returns a reference to the hash.

If you create a new class then the constructor is just sufficient - you  
do not need another method that hides away invocation of YourClass.new.

> Would it be possible to make Hashhash inherit from Hash (by using \<  
> Hash) and be able to use the [][] operator immediately in a way?

Actually, you do not need to create another class (see my earlier  
example). For that it might make sense to create a method that returns  
a new instance with the initialization I have shown.

If you lack explanation: the construct Hash.new {|h,k| …} creates a  
new Hash instance with its default\_proc set to the block you provide.  
This block is invoked whenever there is a key miss. In my case I just  
built it in a way as to create another Hash on the fly with the same  
default\_proc and stuff it in the other Hash. The default\_proc  
propagation ensures you can arbitrarily nest Hashes. Of course, you can  
also do something like this if you know you just need one level of  
nested Hashes

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

Question is whether you want to bother to create a class for this. IMHO  
this makes only sense if you want to put additional logic into it (e.g.  
checking elements that are placed in the Hash).

Kind regards

robert
