time@oxtrap.oxtrap.UUCP (Tim Endres) (10/05/89)
Back in 1984, I suggested to Apple that they adopt an extension to Clascal (what is now called Object Pascal). This extension would be much like the "SELF" keyword, except that it would reference the sender of the message. In other words, SELF refers to the object that received the message, and SENDER would refer to the object that sent the message. At the time, I needed a mutual recursion between two objects, and did not like the fact that I had to pass the second object as a parameter in the message. Apple never responded to this request. Neither did Computer Language magazine, who refused to run the article I had written proposing the construct be given consideration in new OOLs. Does anyone know of a specific OOL implementation of SENDER? Any good reasons why it should not be included?
dchapman@portia.Stanford.EDU (David Chapman) (10/05/89)
In article <TIME.89Oct4131658@oxtrap.oxtrap.UUCP> time@oxtrap.UUCP writes: >Does anyone know of a specific OOL implementation of SENDER? >Any good reasons why it should not be included? I can think of only one reason that _some_ languages wouldn't be able to support a "sender" construct: the sender might not be an object at all. I don't know anything about Object Pascal, but in C++ the sender might be a function instead of another object. Mutual recursion between objects sounds kind of obscure (I use it only in compilers). If it's not going to be used often, a language developer isn't going to want to support it. It's also difficult to add new keywords to existing languages because you invalidate any existing code that happened to use that keyword as an identifier. Can you tell us more about what you were trying to do? Is this something that everyone would want to use?
jima@hplsla.HP.COM (Jim Adcock) (10/06/89)
You should be able to do this using function call overloading in C++. I suspect its not trivial to figure out, however.
dchapman@portia.Stanford.EDU (David Chapman) (10/09/89)
In article <9450008@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes: >You should be able to do this using function call overloading in C++. >I suspect its not trivial to figure out, however. After thinking about this some more, I cannot conceive of a way to implement the "sender" construct. Why? Because the "sender" is of arbitrary type. *Anything* can send an object a message. That's the whole point. Maybe Smalltalk or Flavors could handle this by looking up the type of the object, but it would be horrendous to do in a compiled language like C++. Comments? Remember, the original poster wanted mutual recursion - he wanted to send messages back to the caller.
jima@hplsla.HP.COM (Jim Adcock) (10/10/89)
>dchapman@portia.Stanford.EDU (David Chapman) / 3:40 pm Oct 8, 1989 / >In article <9450008@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes: >>You should be able to do this using function call overloading in C++. >>I suspect its not trivial to figure out, however. > >After thinking about this some more, I cannot conceive of a way to >implement the "sender" construct. Why? Because the "sender" is of >arbitrary type. *Anything* can send an object a message. That's the >whole point. Maybe Smalltalk or Flavors could handle this by looking >up the type of the object, but it would be horrendous to do in a >compiled language like C++. > >Comments? Remember, the original poster wanted mutual recursion - he >wanted to send messages back to the caller. What I was thinking of is that a sender class overloads its function call operator to push the sender "this" onto a stack as a prolog, and pop that "this" as a postlog in the sender function call operator overloading. If no sender class method had been called, then the stack of "sender this's" would be empty. IE "a null sender." Likewise the receiver class function call operator could be overloaded to get a copy of the sender "this" from that stack and interpret it as "sender", adding sender as a parameter to the underlying function call. I suspect this approach would be painful to actually do in C++, since each distinct set of function parameters requires a seperate overloading of the function call operator, and since the receiver functions must themselves be defined as objects of some class, so that operator(something) can be applied to them. Still, an object of a class not obeying the sender protocol could send a message to a receiver, thus the receiver would find an incorrect sender on the stack. But such a protocol-ignoring object would do its dirty work either within a sender method, in which case it could be considered a delegate of the sender, or outside all sender methods, in which case the stack would be empty, and the receiver would note that "no" sender sent the message. An alternate approach is for both sender and receiver to implement these protocols by overloading operator->, and require that any messages sent to either sender or receiver be via "->" as opposed to "." Operator->() seems easier to use as opposed to operator(this, that, ortheotherthing) since there aren't parameters to operator->(). On the other hand, operator->() never regains control after method dispatch, so sender functions would have to explicetely unstack their "this" [which is the receiver's "sender"] before exiting. For mutual recursion, either sender and receiver can be written as the same class, or you can use multiple inheritence to "glue" together both a send/receive capability in a mutual subclass -- assuming sender and receiver are written orthogonally.
andreasg@boulder.Colorado.EDU (Andreas Girgensohn) (10/10/89)
In article <5677@portia.Stanford.EDU> dchapman@Portia.Stanford.EDU (David Chapman) writes: >In article <9450008@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes: >>You should be able to do this using function call overloading in C++. >>I suspect its not trivial to figure out, however. > >After thinking about this some more, I cannot conceive of a way to >implement the "sender" construct. Why? Because the "sender" is of >arbitrary type. *Anything* can send an object a message. That's the >whole point. Maybe Smalltalk or Flavors could handle this by looking >up the type of the object, but it would be horrendous to do in a >compiled language like C++. > >Comments? Remember, the original poster wanted mutual recursion - he >wanted to send messages back to the caller. In Lisp one could do it with a variable with dynamic scope: (defvar sender :no-object) ;;; within every method: (let ((sender self)) ;; message body (actually, the previous value of sender is needed within ;; the body) ) There are no variables with dynamic scope in C. A solution could be an array as a stack of senders (I don't no the C++ syntax). object *senders[200]; int senders_top = 0; senders[0] = (object *)NULL; /* within every method: */ senders[++senders_top] = self; /* message body */ senders_top--;
susser@apple.com (Joshua Susser) (10/11/89)
In Smalltalk-80, it is possible to get a message's sender by evaluating thisContext sender receiver or something close to that. *thisContext* is a pseudovariable that binds to the MethodContext for the current activation record. The *sender* message answers the calling (or sending) context of *thisContext*, and *receiver* returns the *self* binding for that context. It's been about two years since I played with this stuff and I don't have ST80 handy, so I could have missed something here. And ParcPlace could have changed things since then. Also, I believe that Smalltalk/V-PM has a *self sender* construct that returns the sender object. They were going to just make up a *sender* pseudovariable, but George Bosworth said he was worried about creating another reserved word; I think they should have gone for it. I think using a *sender* construct for mutual recursion could be a little messy. I prefer passing the argument explicitly. The place where I think it is most useful is to discriminate between internal and external invocation of a message. This allows private messages, protection, etc. No objects in my eyes, just dust from Bourbon St. Joshua Susser Apple Computer ,Inc. Object Percussionist Advanced Technology Group arpa: susser@apple.com 20525 Mariani Ave. MS 76-2D uucp: {sun,nsc,...}!apple!susser Cupertino, CA 95014 ALink: susser.j 408/974-6997 I beat on objects.
alonzo@microsoft.UUCP (Alonzo Gariepy) (10/12/89)
In article <9450013@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes: > >dchapman@portia.Stanford.EDU (David Chapman) / 3:40 pm Oct 8, 1989 / > >In article <9450008@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes: > >>You should be able to do this using function call overloading in C++. > >>I suspect its not trivial to figure out, however. > > > >After thinking about this some more, I cannot conceive of a way to > >implement the "sender" construct. Why? Because the "sender" is of > >arbitrary type. *Anything* can send an object a message. That's the > >whole point. Maybe Smalltalk or Flavors could handle this by looking > >up the type of the object, but it would be horrendous to do in a > >compiled language like C++. > > > >Comments? Remember, the original poster wanted mutual recursion - he > >wanted to send messages back to the caller. I think the problem here is an attempt to create general language support for a non-general problem. Many of the ideas expressed here do not reflect the best modular design. It is up to an object to define its public interface; it is not good for the sender's address to be obtained without its consent. The provision of this address should be part of an explicit protocol between sender and receiver. In a type safe language such as C++, this should be done by passing a typed pointer to the receiver. You are looking for some syntactical sugar to support a non-general and questionable practice. The basics of modular object-oriented design favour classes that respond to messages and act upon their own state. If an object is going to communicate with an instance of some other class, that knowledge should be part of its state, not just some transitory relationship to a particular sender that exists during the invocation of some method. Remote Procedure Calls and various other kinds of delegation and proxy (such as iterator objects that send some message to all the members of some collection on your behalf) should not have to cope with this concept of sender. I understand the utility of the features being discussed, but they do not merit general support. Alonzo Gariepy // my opinions, not necessarily alonzo@microsoft // those of Microsoft
jpd00964@uxa.cso.uiuc.edu (10/12/89)
/* Written 5:09 pm Oct 11, 1989 by alonzo@microsoft.UUCP in uxa.cso.uiuc.edu:comp.object */ In article <9450013@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes: >> >After thinking about this some more, I cannot conceive of a way to >> >implement the "sender" construct. Why? Because the "sender" is of >> >arbitrary type. *Anything* can send an object a message. That's the >> >whole point. Maybe Smalltalk or Flavors could handle this by looking >> >up the type of the object, but it would be horrendous to do in a >> > >> >Comments? Remember, the original poster wanted mutual recursion - he >> >wanted to send messages back to the caller. > >I think the problem here is an attempt to create general language support >for a non-general problem. Many of the ideas expressed here do not >reflect the best modular design. It is up to an object to define its >public interface; it is not good for the sender's address to be obtained >without its consent. The provision of this address should be part of >an explicit protocol between sender and receiver. In a type safe language >such as C++, this should be done by passing a typed pointer to the >receiver. The sender must still pass its address which means that it must allow someone else to be able to access its instance variables at the called objects will. >You are looking for some syntactical sugar to support a non-general and >questionable practice. The basics of modular object-oriented design >favour classes that respond to messages and act upon their own state. >If an object is going to communicate with an instance of some other >class, that knowledge should be part of its state, not just some transitory >relationship to a particular sender that exists during the invocation of >some method. That may be the theory, but not the practice in Obj-C on the NeXT. A sender is actually encouraged as that limits the amount of irrelevent information sent. A sender is a very very powerful construct which I am sure must be able to be implemented with c++. I do not know of any way offhand, but with a little "syntactical sugar", I am sure someone will come up with a method. Hopefully he will not try to patent it though :-> Michael Rutman Softmed dpd00609@uxa.cso.uiuc.edu
jans@tekgvs.LABS.TEK.COM (Jan Steinman) (10/14/89)
<Does anyone know of a specific OOL implementation of SENDER? Any good reasons
why it should not be included?>
As Joshua Susser pointed out, it is trivial to do in Smalltalk. His
description is quite good, and points out something that many of the C++ people
who have been discussing its difficulty of implementation might have missed:
the sender is identified in the calling stack, and so is simple (although
non-portable) to obtain. An in-line assembly code #define aught to do it.
The bigger question seems to be what is it really good for. I've put it to
*considerable* use in Smalltalk, for mutual recursion as well as other reasons.
It is also invaluable for use in a debugger. (Do you know how long it takes
gdb to print a C++ symbolic stack backtrace on a large application! Hint --
it's coffee time! Tenths of a second typical in Smalltalk.) Another good use
is to elimnate infinite recursion when recursively traversing cyclic graphs --
simply look back the sender chain to see if "self" (or "this") is back there
anywhere. (Keeping a flag around to do this is non-reentrant.)
Another place I've used it was as a "port manager", for controlling a number of
multiplexed devices from a single RS-232 port. Client objects would "register"
with the port manager, who determined their identity through "thisContext
sender receiver". Client objects would simply "read" or "write" without
passing arguments, and each time, the manager discovered who they were and
tacked on the proper MUX address. I find "obj read" or "obj->read()" much more
clean and readable than "obj read: self" or "obj->read(this)".
In short. I think this is one of the best-kept secrets in Smalltalk. It
doesn't appear to be used outside of the debugger in the standard image. I've
added numerous general purpose methods to "thisContext" make more use of
"sender", here's an example: (C++ implementation left as an exercise to the
reader! :-)
!ContextPart methodsFor: 'testing'!
isRecursive
"Does the sender's receiver, method, and arguments appear previously in this
context? Will this context infinitely recurse?"
| ctx rcvr meth |
ctx _ self home.
rcvr _ self receiver.
meth _ self method.
[(ctx _ ctx sender) == nil] whileFalse:
[ctx _ ctx home. "Optimization: skip intervening contexts."
ctx method == meth
and: [ctx receiver == rcvr
and: [self home argsMatch: ctx
and: [^true]]]].
^false!
argsMatch: aContext
"Are the arguments passed to the receiver and <aContext> identical?"
self argCount = aContext argCount ifFalse: [^false].
1 to: self argCount do: [:i |
(self basicAt: i) == (aContext basicAt: i) ifFalse: [^false]].
^true! !
Jan Steinman - N7JDB
Electronic Systems Laboratory
Box 500, MS 50-370, Beaverton, OR 97077
(w)503/627-5881 (h)503/657-7703