From: Robert Klemme Date: 2010-04-06T02:15:11+09:00 Subject: Re: Nested hash On 04/05/2010 04:34 PM, Samuel Smith wrote: > Hello All. > > Sample code: > > class NestedHash < Hash > attr_accessor :val > alias :to_str :to_s > @val=0 > def initialize > blk = lambda {|h,k| h[k] = NestedHash.new(&blk)} > super(&blk) > end > def []= (key,value) > if value.is_a?(NestedHash) > super(key,value) > else > self[key].val=value; > end > end > end > > test=NestedHash.new(); > test['1']='11' > test['1']['2']='12' > test['1']['3']='13' > test['2']['4']='24' > > s=test['1'].val #s='11' > > Work as expected. In C++ by using typecast overloading it is possible to > implement class that will work that way: > s=test['1']# s='11' > > Is it possible to implement same functionality in Ruby? No. Reason: you cannot override variable assignment - you can only override assignment method like you did with []=. > I've tried: > > alias :to_s :to_str > def to_str > @val > end > > But first of all result values are wrong and i can't understand why. > Secondly it works only in constructions like that: > s=" "+test['1'] # ie i must tell Ruby that i need string result > but not in > s=test['1'] # if it were possible to tell Ruby that it use string result > by default > > Any other suggestions? I would disallow mixing nesting and values. Compare it to a filesystem: something is either a directory or not. If it is a directory you can put arbitrary things in it but there is no special file for a certain directory (keeping resource forks and other file system specialties aside for a moment). This is conceptually simpler - and it also makes the implementation easier because you do not need an extra class for this: robert@fussel:~$ ruby19 -e 'ha=Hash.new {|h,k| h[k]=Hash.new(&h.default_proc)};ha[1][2][3]=4;p ha' {1=>{2=>{3=>4}}} robert@fussel:~$ Depending on the context a totally different approach might be even more reasonable: if the types you want to nest are known you could create a set of Struct classes that exactly represent what you want to model. Of course this approach does not work with a generic mechanism (e.g. storing a different representation of any XML document). Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/