[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re(2): when should sends be virtual?




Have you studied Henry Liebermann's paper on prototypes and delegation
in OOPSLA'86?
I believe it was the first to use delegation in this area
and that it did define it to be what C++'ers would call "virtual".
If this is correct, then it can be very confusing to use the word
"delegation" is a CS context to mean "just do this and don't bother me
again".
After all, that is what "message sending" and "forwarding" mean.
So, please read this paper, and if you agree with the above,
you might want to either avoid the word, or use it only in its
original technical sense, otherwise you can confuse people.

There is also a paper called "Parents are Shared Parts of Objects;
A Shared View of Sharing" (or something like that) that
we published a while back in a special issue of the Journal
of Lisp and Functional Programming. I think it is available by ftp
from self.stanford.edu. Although it was written a while ago,
I think that its discussion of this issue is a better explanation of
at least my position than I could convey in e-mail.

I suspect that much has already been said on both sides of this one--
you might enjoy reading more of the many paper on this topic.

- Dave



 ------ From: Rainer Blome, Wed, Jan 18, 1995 ------ 

hi again.

these are some remarks that i thoght to be of general interest, taken from
my reply to a mail from guenter kniesel, so they may sometimes appear to be
somewhat out of context.  (my original posting included a rather serious
flaw if one read it literally since accidentally wrote `ancestors' instead
of `descendants'.  see below.)

no quote if rom my reply, single quote `> 'is from guenter, double quote
`>> ' is from my original message.



>> who is the parent of the method?
what i meant is:  if some selector is not found in the activation record,
which is the object where the lookup will continue (`method parent')?


> This is the very semantics of the notion of "self" / "this" / "current".

what do you mean with `very semantics'?
here's a little story: (respective meanings of metaphors in parentheses)

imagine Frank (object) in some work hierarchy (delegation
chain) being asked to foo (receives unary message).  he doesn't know how
to foo (lookup failed) and delegates this to his superior Sabine (parent).
Sabine knows how to foo (lookup succeeded).  she gets the scrap of paper
with the instructions (code) and follows them: the first line says
"bar!" (exclamation point instead of full stop used for clarity)
aha, this is an instruction for herself (huh?). END OF STORY

in self as it is, this is to say that message bar is to be sent to implicit
self.  but now, who should execute these instructions?  Sabine?  or should
she lend that scrap of paper to Frank so he may do what he was asked to do?

then what does delegation mean, actually?  in the `real' world, `to
delegate' surely means to have the other guy actually do it, not just tell
one how to do it.  mommy, i don't know how to do this, will you do it for
me, please?  this is what a naive observer would expect self to work like.

the current practice seems counterintuitive to me.  it looks more like the
`shared slots' way of sharing (inheriting) behavior, as if all the
ancestor's slots were directly present in an object (except the overridden
ones).

>> and it is 'non-virtual' when lookup starts in y, being the holder of
>> bar. ...
when i said `it is non-virtual', i meant `i call it non-virtual'.


>> ...  in self, this is called an 'undirected resend'.
> So explicit undirected resends only say where to ... restart the search.
true.  undirected resend is indeed not what i called non-virtual.


non-virtual would mean that self is set to y resp. Sabine resp. to the
holder of any method that sends to implicit self.  this kind of send
semantics is missing in self, if i am not missing anything.  it might be
simulated by some delegation primitive though.


>> shouldn't it always have to be made explicit when the result of a lookup
>> cannot be determined by the sender?  dynamic inheritance set aside, a
>> method 'knows' the behavior (of its ancestors) it can rely on when doing
>> a non-virtual send.  it seems like good style to me to make it explicit
>> when one relies on things that are uncertain.

of course one cannot surely determine the result of a lookup beforehand,
that's the good thing about dynamic inheritance.

but if y holds methods foo and frob, and the programmer wants to invoke
frob from foo and is sure that she wants the frob in y and nowhere else,
she can't enforce it in self!  (except when she knows that y may be reached
by sending message `y' to self, that'd be even messier.)


>> making non-virtual sends the default would also give an easy answer
>> for a question discussed here some weeks ago: how to determine what
>> behavior some objects rely on their childs to supply it.  simply look
>> for virtual sends instead of having to check whether a send to self is
>> already implemented in the object or its ancestors.

> I don't see how looking at the code of children can help to determine
> what _parent_ objects expect from their descendants. The children
> only show what _they_ expect from their parents.

OOPS, i meant descendants, not ancestors.


>> did anybody ever see a treatise about where and when it should be
>> specified that a message send should be virtual?  at the send site?
> Some languages / type systems specify "fixed" types, i.e. variables
> that cannot be substituted by values of subtypes. Here static binding
> can be always done. If you are deeply interested I can provide you
> some references.

no thanks, my eyes would hurt if i saw that ... ;-)


>> or at the declaration/implementation of a method?
> That is being done in Simula, Beta, C++, ...
*clonk* (simula and beta just dropped in interestingness coz this means
they are statically typed, right?)

to summarize once again:
the decision whether a send should be virtual
should be made at the send site.  maybe this demands having two of these
global object-references, `holder' and `receiver of last message to
non-self'.
as i see it, what we mean by `holder' is closer to the common-sense meaning
of `self' than what `self' currently means in Self (sic!).

another issue is concurrency/asynchronous sends:
easy with the holder-is-self semantics (except for actual synchronization
problems like access);
with the `shared methods' semantics, it becomes impossible when the unit of
concurrency is the object.



<a href="http://namu19.gwdg.de/rblome";>Rainer Blome</a>