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

Eric Mahurin wrote:

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
[...]

This looks very interesting, if only from the toying standpoint. Any chance of you pushing this a bit with a RubyForge project and a gem release?