On Tue, Jan 26, 2010 at 3:29 PM, Glen Holcomb <damnbigman / gmail.com> wrote:
> 2010/1/26 Jes Gabriel y Gal <jgabrielygalan / gmail.com>
>
>> On Mon, Jan 25, 2010 at 10:49 PM, Glen Holcomb <damnbigman / gmail.com>
>> wrote:
>>
>> > Exactly, infinite depth would be nice as it would make a more temporally
>> > portable solution.
>>
>> With it, you have infinite depth, until in a branch you decide to stop
>> by appending (<<) a value.
>> Then you fix the depth of that branch.
>>
>> > The proxy looks to be working great.  am a bit
>> > confused as to why the << method in the proxy doesn't overwrite a leaf
>> with
>> > a new array though. 'm not complaining as it works the way I want it
>> to,
>> > I'm just perplexed.
>>
>> When you access h[1][2][3], a proxy object is inserted in the hash for
>> that key. The proxy object remembers the hash and the key. When you
>> call << on the proxy object, it replaces itself in the hash with an
>> empty array, to which it appends the value. So further calls to
>> h[1][2][3] will return that array and no proxy objects anymore. It
>> works the same for the upper levels: calling h[1] inserts a proxy in
>> the hash. When you call [] on it (for example h[1][2]) it replaces
>> h[1] with a hash.
>>
>> Maybe this clarifies a bit more:
>>
>>
>> /temp$ cat nested_hash_array.rb && ruby nested_hash_array.rb
>> class ProxyDefault
>> ef initialize hash, key
>> hash = hash
>> key = key
>> nd
>>
>> ef [](key)
>> puts "the hash is: #{@hash.inspect} whenalling [] on the
>> proxy object"
>> @hash[@key] = Hash.new {|hash,key| ProxyDefault.new(hash,
>> key)}
>> puts "the hash is: #{@hash.inspect} after replacing the
>> proxy with a hash"
>> hash[@key][key]
>> nd
>>
>> ef << value
>> uts "the hash is: #{@hash.inspect} when calling << on the
>> proxy object"
>> hash[@key] = [value]
>> uts "the hash is: #{@hash.inspect} aftereplacing the
>> proxy with an array"
>> hash[@key]
>> end
>> end
>>
>> h = Hash.new {|hash,value| ProxyDefault.new(hash, value)}
>>
>> h[1][2] << "value"
>>
>> p h
>> p h[1][2]
>>
>> the hash is: {} when calling [] on the proxy object
>> the hash is: {1=>{}} after replacing the proxy with a hash
>> the hash is: {} when calling << on the proxy object
>> the hash is: {2=>["value"]} after replacing the proxy with an array
>> {1=>{2=>["value"]}}
>> ["value"]
>>
>> Jesus.
>>
>>
> Sorry, I should have been more specific when stating my confusion.  am
> confused as to why appending a second item into a leaf results in a
> multi-item array rather than a new array with only the second item.
>
> data[1][2][3] << 4
> data[1][2][3] << 5
>
> yields
> 1=>{2=>{3=>[4,5]}}}
> looing at the proxy I was expecting
> 1=>{2=>{3=>[5]}}}
>
> The behavior I'm seeing is what I want I just didn't expect it. rom the
> code it looks like << assigns an array to the key then appends a value. 
> was expecting that to overwrite the array created with the first << call at
> that level with a new single item array.

I understood your question, so this means I explained myself really badly :-).
When you do this:

h[1] << 4

The following things happen:

- The method [] of h is called with parameter 1
- The hash detects that there's no entry for that key, and so calls
the default proc
- The default proc inserts a Proxy object in the hash for that key
(this proxy object remembers the hash and the key)
- The result of the default proc (which is the proxy object itself) is returned
- The method << with parameter 4 is called on the proxy object
- That method removes the proxy object from the hash and replaces
itself with an array with element 4 inside.

From now on, every time you call h[1] there is actually a value in the
hash, which is the array created by the proxy, and so the hash doesn't
call the default proc anymore, and no other proxy object is involved.
Subsequent calls to h[1] << some_value will actually call the <<
method of the array.

Hope this clears up the issue a little bit more.

Jesus.