From: Glen Holcomb Date: 2010-01-27T02:06:54+09:00 Subject: Re: Nested hash with arrays for default value --000325559bbadb1ae6047e144f24 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable 2010/1/26 Jes=FAs Gabriel y Gal=E1n > On Tue, Jan 26, 2010 at 3:29 PM, Glen Holcomb > wrote: > > 2010/1/26 Jes=FAs Gabriel y Gal=E1n > > > >> On Mon, Jan 25, 2010 at 10:49 PM, Glen Holcomb > >> 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. I am a bit > >> > confused as to why the << method in the proxy doesn't overwrite a le= af > >> with > >> > a new array though. I'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 > >> def initialize hash, key > >> @hash =3D hash > >> @key =3D key > >> end > >> > >> def [](key) > >> puts "the hash is: #{@hash.inspect} when calling [] on > the > >> proxy object" > >> @hash[@key] =3D Hash.new {|hash,key| > ProxyDefault.new(hash, > >> key)} > >> puts "the hash is: #{@hash.inspect} after replacing th= e > >> proxy with a hash" > >> @hash[@key][key] > >> end > >> > >> def << value > >> puts "the hash is: #{@hash.inspect} when calling << on > the > >> proxy object" > >> @hash[@key] =3D [value] > >> puts "the hash is: #{@hash.inspect} after replacing the > >> proxy with an array" > >> @hash[@key] > >> end > >> end > >> > >> h =3D 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=3D>{}} after replacing the proxy with a hash > >> the hash is: {} when calling << on the proxy object > >> the hash is: {2=3D>["value"]} after replacing the proxy with an array > >> {1=3D>{2=3D>["value"]}} > >> ["value"] > >> > >> Jesus. > >> > >> > > Sorry, I should have been more specific when stating my confusion. I a= m > > 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=3D>{2=3D>{3=3D>[4,5]}}} > > looing at the proxy I was expecting > > {1=3D>{2=3D>{3=3D>[5]}}} > > > > The behavior I'm seeing is what I want I just didn't expect it. From t= he > > code it looks like << assigns an array to the key then appends a value. > I > > was expecting that to overwrite the array created with the first << cal= l > 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. > > No, you didn't acutally. I just wasn't thinking about it properly. When I actually think about your explanation further the whole *no more proxy object* makes perfect sense and answers my question. Thanks for your patience and help Jesus. It is appreciated. --=20 "Hey brother Christian with your high and mighty errand, Your actions speak so loud, I can=92t hear a word you=92re saying." -Greg Graffin (Bad Religion) --000325559bbadb1ae6047e144f24--