From: Eric Mahurin Date: 2005-05-05T14:51:38+09:00 Subject: Re: object reference handle (like perl's reference to scalar) Below is what I think is a general purpose solution to making references. I provide several ways to do it. Here is an example: a = (0..5).to_a -> [0,1,2,3,4,5] w = ref{"a[2..4]"} # uses eval x = a.ref[2..4] # uses [] and []= methods y = a.ref("[]","[]=",2..4) # specify methods manually z = a.ref(["[]",2..4],["[]=",2..4]) # unique args to get/set w[] -> [2,3,4] x[] -> [2,3,4] y[] -> [2,3,4] z[] -> [2,3,4] w[]=(11..14).to_a a -> [0,1,11,12,13,14,5] x[]=[4,3,2] a -> [0,1,4,3,2,14,5] y[]=[0,1] a -> [0,1,0,1,14,5] z[]=[2,3,4] a -> [0,1,2,3,4,5] You should be able to use this with any object attribute methods, get/set method pairs, variable references, etc. It should be quite a bit more powerful than perl references. This is not implemented at all like C/C++ pointers, but the function is the same (and much safer). ------------- class Object class ReferenceMaker def initialize(obj) @obj = obj end def method_missing(method,*args) get = @obj.method(method) set = @obj.method(method.to_s<<"=") if args.size>0 getter = proc { |*a| get[*(args+a)] } setter = proc { |*a| set[*(args+a)] } else getter = get setter = set end Reference.new(getter,setter) end end def ref(*args,&block) if block symbol = block[].to_s scope = block.binding if symbol[-1]=="]"[0] get = symbol.clone get[-1,0] = ",*_a" set = symbol.clone set[-1,1] = ",*(_a[0,_a.size-1])]=_a[-1]" elsif symbol[-1]==")"[0] get = symbol.clone get[-1,0] = ",*_a" set = get.clone set["("] = "=(" else get = "if _a.size>0 then #{symbol}(*_a) else #{symbol} end" set = "if _a.size==1 then #{symbol}=_a[0] else #{symbol}=(*_a) end" end get = eval("proc { |*_a| #{get} }", scope) set = eval("proc { |*_a| #{set} }", scope) if args.size>0 getter = proc { |*a| get[*(args+a)] } setter = proc { |*a| set[*(args+a)] } else getter = get setter = set end Reference.new(getter,setter) elsif args.size>0 get,set,*args = *args if get.kind_of?Array get,*getargs = *(get+args) else getargs = args end set ||= (get.to_s<<"=") if set.kind_of?Array set,*setargs = *(set+args) else setargs = args end get = self.method(get) set = self.method(set) if getargs.size>0 then getter = proc { |*a| get[*(getargs+a)] } else getter = get end if setargs.size>0 then setter = proc { |*a| set[*(setargs+a)] } else setter = set end Reference.new(getter,setter) else ReferenceMaker.new(self) end end end class Reference def initialize(getter,setter) @getter = getter @setter = setter end def [](*args) @getter[*args] end def []=(*args) @setter[*args] end end Discover Yahoo! Find restaurants, movies, travel and more fun for the weekend. Check it out! http://discover.yahoo.com/weekend.html