[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Hash.new with a block?

7stud 7stud

9/3/2007 4:50:00 AM

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.
--
Posted via http://www.ruby-....

5 Answers

Robert Klemme

9/3/2007 5:51:00 AM

0

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

7stud 7stud

9/3/2007 6:32:00 AM

0

Robert Klemme 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.
--
Posted via http://www.ruby-....

Alex Gutteridge

9/3/2007 7:05:00 AM

0

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

> Robert Klemme 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.

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 Gutteridge

Bioinformatics Center
Kyoto University



7stud 7stud

9/3/2007 7:22:00 AM

0

Alex Gutteridge 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


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

Alex Gutteridge

9/3/2007 8:03:00 AM

0

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

> Alex Gutteridge 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

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 Gutteridge

Bioinformatics Center
Kyoto University