# Hash.new with a block?

**URL:** <https://www.ruby-forum.com/t/hash-new-with-a-block/113633>\
**Category:** Ruby\
**Created:** [September 3, 2007, 6:50am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633 "2007-09-03T06:50:10Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [September 3, 2007, 6:50am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633/1 "2007-09-03T06:50:10Z")

</div>

Hi,

In the code:

h = Hash.new {|hash, key| hash[key] = []}

what method is yielding the values hash, key to the code block? It  
doesn’t seem like it could be new() since new() isn’t called when you  
lookup a key in a hash. Does new() somehow associate that block with  
the method [] in Hash?

Thanks.

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [September 3, 2007, 7:55am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633/2 "2007-09-03T07:55:31Z")

</div>

On 03.09.2007 06:50, 7stud – wrote:

> In the code:
> 
> h = Hash.new {|hash, key| hash[key] = []}
> 
> what method is yielding the values hash, key to the code block? It  
> doesn’t seem like it could be new() since new() isn’t called when you  
> lookup a key in a hash. Does new() somehow associate that block with  
> the method [] in Hash?

$ ruby -e ‘h=Hash.new {|h,k| h[k]=[]}; set\_trace\_func(lambda {|\*a| p  
a}); h[1]\<\<2’  
[“line”, “-e”, 1, nil, #Binding:0x1002fdf4, false]  
[“c-call”, “-e”, 1, :[], #Binding:0x1002fdb8, Hash]  
[“c-call”, “-e”, 1, :default, #Binding:0x1002fca0, Hash]  
[“c-call”, “-e”, 1, :call, #Binding:0x1002fb9c, Proc]  
[“line”, “-e”, 1, nil, #Binding:0x1002f9a8, false]  
[“c-call”, “-e”, 1, :[]=, #Binding:0x1002f8a4, Hash]  
[“c-return”, “-e”, 1, :[]=, #Binding:0x1002f868, Hash]  
[“c-return”, “-e”, 1, :call, #Binding:0x1002f778, Proc]  
[“c-return”, “-e”, 1, :default, #Binding:0x1002f688, Hash]  
[“c-return”, “-e”, 1, :[], #Binding:0x1002f598, Hash]  
[“c-call”, “-e”, 1, :\<\<, #Binding:0x1002f4a8, Array]  
[“c-return”, “-e”, 1, :\<\<, #Binding:0x1002f3b8, Array]

I believe there’s also some explanation in the documentation.

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [September 3, 2007, 8:31am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633/3 "2007-09-03T08:31:42Z")

</div>

Robert K. wrote:

> $ ruby -e ‘h=Hash.new {|h,k| h[k]=[]}; set\_trace\_func(lambda {|\*a| p  
> a}); h[1]\<\<2’  
> [“line”, “-e”, 1, nil, #Binding:0x1002fdf4, false]  
> [“c-call”, “-e”, 1, :[], #Binding:0x1002fdb8, Hash]  
> [“c-call”, “-e”, 1, :default, #Binding:0x1002fca0, Hash]  
> [“c-call”, “-e”, 1, :call, #Binding:0x1002fb9c, Proc]  
> [“line”, “-e”, 1, nil, #Binding:0x1002f9a8, false]  
> [“c-call”, “-e”, 1, :[]=, #Binding:0x1002f8a4, Hash]  
> [“c-return”, “-e”, 1, :[]=, #Binding:0x1002f868, Hash]  
> [“c-return”, “-e”, 1, :call, #Binding:0x1002f778, Proc]  
> [“c-return”, “-e”, 1, :default, #Binding:0x1002f688, Hash]  
> [“c-return”, “-e”, 1, :[], #Binding:0x1002f598, Hash]  
> [“c-call”, “-e”, 1, :\<\<, #Binding:0x1002f4a8, Array]  
> [“c-return”, “-e”, 1, :\<\<, #Binding:0x1002f3b8, Array]
> 
> I believe there’s also some explanation in the documentation.

I don’t know what that output means. I have also looked up Hash.new in  
the book “Programming Ruby (2nd ed)” and it doesn’t mention anything  
about the particulars. The same documentation is displayed when I type:

$ri Hash.new  
…If a block is specified, it will be called with the hash object  
and the key, and  
should return the default value. It is the block’s responsibility  
to store the value in the hash if required.

So, as far as I can tell, the Ruby documentation doesn’t help with my  
question.

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [September 3, 2007, 9:05am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633/4 "2007-09-03T09:05:42Z")

</div>

On 3 Sep 2007, at 15:31, 7stud – wrote:

> > [“c-return”, “-e”, 1, :call, #Binding:0x1002f778, Proc]  
> > [“c-return”, “-e”, 1, :default, #Binding:0x1002f688, Hash]  
> > [“c-return”, “-e”, 1, :[], #Binding:0x1002f598, Hash]  
> > [“c-call”, “-e”, 1, :\<\<, #Binding:0x1002f4a8, Array]  
> > [“c-return”, “-e”, 1, :\<\<, #Binding:0x1002f3b8, Array]
> > 
> > I believe there’s also some explanation in the documentation.
> 
> I don’t know what that output means.

Each line shows an ‘event’ occurring in the script. Where event is  
calling a C method, returning, etc… (see Kernel#set\_trace\_func). We  
can summarise what’s going on:

> > [“line”, “-e”, 1, nil, #Binding:0x1002fdf4, false]

Process new line.

> > [“c-call”, “-e”, 1, :[], #Binding:0x1002fdb8, Hash]

Call the C method Hash#[]

> > [“c-call”, “-e”, 1, :default, #Binding:0x1002fca0, Hash]

Call the C method Hash#default.

> > [“c-call”, “-e”, 1, :call, #Binding:0x1002fb9c, Proc]

Call the C method Proc#call. This Proc is the one given to Hash.new I  
guess. Here is the answer to your original question.

> > [“line”, “-e”, 1, nil, #Binding:0x1002f9a8, false]

I guess this means we’ve moved into the Proc

> > [“c-call”, “-e”, 1, :[]=, #Binding:0x1002f8a4, Hash]

We call Hash#[] inside our Proc

> > [“c-return”, “-e”, 1, :[]=, #Binding:0x1002f868, Hash]  
> > [“c-return”, “-e”, 1, :call, #Binding:0x1002f778, Proc]  
> > [“c-return”, “-e”, 1, :default, #Binding:0x1002f688, Hash]  
> > [“c-return”, “-e”, 1, :[], #Binding:0x1002f598, Hash]

Return from each of the previous calls.

> > [“c-call”, “-e”, 1, :\<\<, #Binding:0x1002f4a8, Array]  
> > [“c-return”, “-e”, 1, :\<\<, #Binding:0x1002f3b8, Array]

Push something onto the Array.

So short answer: Hash#[] calls Hash#default which in the case of Hash  
objects with an associated Proc calls the Proc.

Alex G.

Bioinformatics Center  
Kyoto University

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [September 3, 2007, 9:21am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633/5 "2007-09-03T09:21:32Z")

</div>

Alex G. wrote:

> So short answer: Hash#[] calls Hash#default which in the case of Hash  
> objects with an associated Proc calls the Proc.

Thanks for the explanation. So, is correct to assume that in the source  
code for Hash#default there is a line somewhere that says something  
like:

yield hash, key

---

<div class="post-metadata">

**Author:** ![7stud](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/7/57b2e6/32.png) [@7stud](https://www.ruby-forum.com/u/7stud)\
**Post date:** [September 3, 2007, 10:03am UTC](https://www.ruby-forum.com/t/hash-new-with-a-block/113633/6 "2007-09-03T10:03:48Z")

</div>

On 3 Sep 2007, at 16:21, 7stud – wrote:

> yield hash, key  
> Well proc.call(hash,key) really, which is almost (sort of) the same  
> thing! Here is the source code from hash.c with my comments:

static VALUE rb\_hash\_default(argc, argv, hash){  
VALUE key;

```
 rb_scan_args(argc, argv, "01", &key);
 if (FL_TEST(hash, HASH_PROC_DEFAULT)) { //Test if default Proc

```

is present  
if (argc == 0) return Qnil;  
return rb\_funcall(RHASH(hash)-\>ifnone, id\_call, 2, hash,  
key); //If so call the procs ‘call’ method  
}  
//with ‘hash’ and ‘key’ as args  
return RHASH(hash)-\>ifnone;  
}

Alex G.

Bioinformatics Center  
Kyoto University
