[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: object reference handle (like perl's reference to scalar

Eric Mahurin

5/5/2005 5:52:00 AM

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/we...



1 Answer

Florian Groß

5/5/2005 4:19:00 PM

0

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?