[squeak-dev] what is a transparent proxy?
asqueaker at gmail.com
Mon Jan 17 21:43:11 UTC 2022
> my understanding of a "transparent proxy" is that it automatically forwards all requests, thus requiring special metaprogramming logic to reveal an object as a proxy. On the other hand, "intransparent proxies" would define an explicit list of requests to forward. Not sure however whether this is a useful classification ...
Then there is a balance between those two, traditional "Proxy", which
defines an explicit list of requests NOT to forward, any message not
in the list is automatically forwarded.
That explicit list of requests is the API to the proxy, the
"metaprogramming logic" you alluded to, above. As a Smalltalker, I
like to have that API defined on ProtoObject with "__" or "basic"
prefixes; i.e., #__class or #basicClass. There could be one for each
mirror primitive, and nothing else. That's my preferred aesthetic,
but the aesthetic of the Proxy API is less important to me than the
handling semantics needed throughout the code.
> > > - ProtoObject is still not yet an empty class.
> > > For instance, stuff such as #doOnlyOnce: or #scaledIdentityHash should be implemented on Object only.
That means Proxies could not be members of any HashedCollections
without forcing reification.
However, I agree it's a lot easier and safer for a user to add that
one than remove it.
> We should continue work on this in the Trunk. You can mitigate this by redefining these messages in your proxy and forwarding them yourself.
> I really think this would a small pattern which should be no huge effort to apply to all <primitive:> sends in the Trunk. :-) How could we best design such a pattern? For instance, looking at Object >> #at:
> We could insert this statement at the beginning of the method:
> (index isInteger and: [((thisContext objectClass: index) includesBehavior: Integer) not]) ifTrue:
> [^ self at: index yourself].
> Object>>#perform:withArguments:inSuperclass: could be rewritten like this:
> perform: selector withArguments: argArray inSuperclass: lookupClass
> <primitive: 100>
> + (selector isSymbol and: [((thisContext objectClass: selector) includesBehavior: Symbol) not])
> ifTrue: [^ self perform: selector yourself withArguments: argArray inSuperclass: lookupClass].
> (selector isSymbol)
That looks good. Regardless of the specific implementation details,
+1000 to the *concept* of allowing Squeak to support the classic Proxy
pattern! And it should be pushed as low into the code as it can to
maximize usage transparency. (I realized your definition of
"transparent" was a function of the implementation, mine is a function
of their usage).
I'm not against a VM-based proxy system at all, the more options the
better. It's just that we've allowed our anticipation of it to allow
Squeak's support for the classic Smalltalk Proxy pattern to get broken
(because of Symbol>>#=), so we currently have no options at all.
>  http://lists.squeakfoundation.org/pipermail/squeak-dev/2022-January/218221.html
More information about the Squeak-dev