From: Paul Brannan Date: 2001-09-28T01:28:32+09:00 Subject: [ruby-talk:21779] Re: Transparent Proxies On Thu, 27 Sep 2001, Jason Voegele wrote: > Hello all, > > I'm trying to implement a persistent object store similar to an Object > Oriented Database. One feature of this object store is on-demand > loading of objects, such that an object is only loaded from the > database when it is needed. Sounds interesting. > I've been thinking about the various ways to implement this but have > not come up with a satisfactory solution. There was some time back a > discussion about the possibility of adding a "become" feature (ala > Smalltalk) to Ruby that would provide exactly what I need, but it > appears that there were many problems with "become" that prevent it > from being added to the language. I know also that there is a > standard "delegate" package for Ruby, but there are other problems > with this, such as "delegate.class" won't return the right thing, and > seemingly severe performance problems noted in this post: > > http://groups.google.com/groups?q=delegate&hl=en&group=comp.lang.ruby&rnum=4&selm=fWQS6.109749%24I5.25755148%40news1.rdc1.tn.home.com Interesting that the post you mentioned never made it to ruby-talk. I think that was from when the link between the list and the newsgroup was temporarily broken. Part of my problem in that post was that I was not correctly using delegate. What I did was this: class B < SimpleDelegator def initialize @a = A.new super(@a) end end but I now know that what I should have done was this: class B < DelegateClass(A) def initialize @a = A.new super(@a) end end Additionally, an alternative implememtation for class C would have been: class C def initialize @a = A.new end def method_missing(*message) @a.__send__(*message) end end using this approach, DelegateClass(Foo) and the "method_missing hack" produce very close timing results. The reason SimpleDelegate is so slow is that it must create new delegate methods every time a new object is created; DelegateClass(Foo) does this only once, when the class itself is created. However, if Foo changes (i.e. if methods are added or removed) then DelegateClass(Foo) will not not get the new methods, and it will still try to delegate the removed methods. > What I'm looking for is a means of implementing a transparent proxy, > such that things like "proxy.class" work as expected and allows the > proxy to be replaced with the actual object when it becomes necessary, > and all of this without being "too" slow. Any ideas? One thing I considered doing in ROMP (which is a proxy over a network) was to override type() and class() in the proxy object to return the class of the object on the other side. I decided against doing this, though, because it might be useful to know whether I am talking to a proxy object or whether I am talking to a real object (of course, singe methods can be added/removed from an object at run-time, knowing the "type" of an object isn't exceptionally useful information anyway; responds_to? is a much better option in many cases). > C++ tends to do this by allowing pointers to "fault" and catching the > exception. I don't think I can do this in Ruby, and I'm not sure that > I'd want to anyway. I'm not sure what you mean here. Can you provide an example? Paul