abbott@aerospace.aero.org (Russell J. Abbott) (08/18/89)
One feature I want to include in a browsing system I'm building is to let users capture, edit, and then replay sequences of browsing operations. Is there a good way to do that in smalltalk? -- -- (Russ) abbott@itro3.aero.org
abbott@aerospace.aero.org (Russell J. Abbott) (08/19/89)
In article <56231@aerospace.AERO.ORG> I wrote: > One feature I want to include in a browsing system I'm building is to > let users capture, edit, and then replay sequences of browsing > operations. Is there a good way to do that in smalltalk? This seems to be a special case of a more general problem. I've also been thinking about how to implement Prolog-like logical variables in Smalltalk. The obvious thing would be to define a class called Variable with one instance variable for the variable's referenced value, if any. The problem this raises is that one wants to be able to send to Variable objects messages to be passed on to the variable's referent. But in order for the variable to be able to do that it has to have built into it selectors for all the possible calls it's referents may ever receive, which is impossible. What is really needed is some sort of meta-method that can handle any call. But as far as I know, smalltalk doesn't support such a thing. (Is that true? I'm really just a smalltalk novice.) One would need a similar capability if one wanted to write some sort of interpreter which could accept any call at all. If one had such an interpreter one could build the history maintainer I asked for originally. How does the smalltalk world handle the need for this sort of thing?-- -- Russ abbott@itro3.aero.org
bnfb@Apple.COM (Bjorn Freeman-Benson) (08/19/89)
In article <56248@aerospace.AERO.ORG> (Russell J. Abbott) writes: > ... >objects messages to be passed on to the variable's referent. But in >order for the variable to be able to do that it has to have built into >it selectors for all the possible calls it's referents may ever receive, You can do this by reimplementing doesNotUnderstand: aMessage for your Variable class. When an object gets sent a message that it does not have a method for, it calls this routine. The default behavior (in Object) is to put up an error notification. For your Variable class, the method would be: doesNotUnderstand: aMessage ^referent perform: aMessage selector withArguments: aMessage arguments And then, of course, you get into the problem of "the name of a thing" versing itself". When you send "getReferent" to the Variable it handles the message. But what if you wanted to send "getReferent" to the Variable's referent? Arg. But, that's a seperate problem... Bjorn N. Freeman-Benson
arshad@lfcs.ed.ac.uk (Arshad Mahmood) (08/21/89)
In article <56248@aerospace.AERO.ORG> abbott@aero.UUCP (Russell J. Abbott) writes: >In article <56231@aerospace.AERO.ORG> I wrote: >> One feature I want to include in a browsing system I'm building is to >> let users capture, edit, and then replay sequences of browsing >> operations. Is there a good way to do that in smalltalk? > >This seems to be a special case of a more general problem. I've also >been thinking about how to implement Prolog-like logical variables in >Smalltalk. The obvious thing would be to define a class called Variable >with one instance variable for the variable's referenced value, if any. >The problem this raises is that one wants to be able to send to Variable >objects messages to be passed on to the variable's referent. But in >order for the variable to be able to do that it has to have built into >it selectors for all the possible calls it's referents may ever receive, >which is impossible. What is really needed is some sort of meta-method >that can handle any call. But as far as I know, smalltalk doesn't >support such a thing. (Is that true? I'm really just a smalltalk >novice.) > >One would need a similar capability if one wanted to write some sort of >interpreter which could accept any call at all. If one had such an >interpreter one could build the history maintainer I asked for >originally. How does the smalltalk world handle the need for this sort >of thing?-- >-- Russ abbott@itro3.aero.org Try trapping the message in Object. doesNotUnderstand: aMessage "First check for a compound selector. If found, try copying down code into the receiver's class. If this is unsuccessful, announce that the receiver does not understand the argument, aMessage, as a message. The default behavior is to create a Notifier containing the appropriate message and to allow the user to open a Debugger. Subclasses can override this message in order to modify this behavior." | status gripe | status _ self class tryCopyingCodeFor: aMessage selector. status==#OK ifTrue: [^self perform: aMessage selector withArguments: aMessage arguments]. gripe _ status==#HierarchyViolation ifTrue: [aMessage selector classPart , ' is not one of my superclasses: '] ifFalse: ['Message not understood: ']. NotifierView openContext: thisContext label: gripe , aMessage selector contents: thisContext shortStack. "Try the message again if the programmer decides to proceed." ^self perform: aMessage selector withArguments: aMessage arguments ------ This is the method which notifies you of the fact that the message is not understood. The message itself is in aMessage and you can do pretyy much anything you like with it. Hope this helps. Note: I have not had a chance to try this on our machines since they're rather heavily used, but there is no reason why this shouldn't work. A. Mahmood Laboratory for Foundations of Computer Science Edinburgh University Scotland e-mail: arshad@lfcs.edinburgh.ac.uk
arshad@lfcs.ed.ac.uk (Arshad Mahmood) (08/21/89)
oops, he notices just after his sent it that some kind soul has answered the same question on comp.land.smalltalk. But since the prolog people may not read the smalltalk bb, it may still be of minute use. sorry.
bruce@servio.UUCP (Bruce Schuchardt) (08/22/89)
In article <34138@apple.Apple.COM> bnfb@Apple.COM (Bjorn Freeman-Benson) writes: >In article <56248@aerospace.AERO.ORG> (Russell J. Abbott) writes: >> ... >>objects messages to be passed on to the variable's referent. But in >>order for the variable to be able to do that it has to have built into >>it selectors for all the possible calls it's referents may ever receive, > >You can do this by reimplementing > doesNotUnderstand: aMessage >for your Variable class. When an object gets sent a message that it >does not have a method for, it calls this routine. The default >behavior (in Object) is to put up an error notification. For your >Variable class, the method would be: > doesNotUnderstand: aMessage > ^referent perform: aMessage selector withArguments: aMessage arguments > >And then, of course, you get into the problem of "the name of a >thing" versing itself". When you send "getReferent" to the Variable >it handles the message. But what if you wanted to send >"getReferent" to the Variable's referent? Arg. > There are some pitfalls in using proxy objects like this that you should be aware of. The first is *speed degradation*. The second is *special messages*. When you use the "doesNotUnderstand:" route of trapping messages, you are introducing some serious extra processing into your system. The interpreter must hunt through the forwarder's class hierarchies method dictionaries to determine that the message has not been implemented. It must then build a message object (to hold the selector and arguments) and search the hierarchy again for your "doesNotUnderstand:" method. I would not recommend using this approach for compute-intensive applications. In any case, it can be made most efficient by nilling out the superclass of the forwarder class after it has been created. This is more work, but you will end up with a faster forwarder. The second problem concerns special messages. You all probably saw the message last week about the "value" method in contexts. In Smalltalk-80, and evidently Smalltalk/V, some messages are treated extra special by the compiler/interpreter. They don't go through message lookup, but are trapped and executed immediately. Examples are "value" and "==". ParcPlace Smalltalk-80 keeps a list of special selectors in a class variable in SystemDictionary. YOU WILL NOT BE ABLE TO TRAP THESE MESSAGES unless you change the compiler or recompile everything to use different selectors. -- -------- -------------- | Bruce Schuchardt Ph: (503) 629-8383 | | Beaverton, OR uunet!servio!bruce | -------------- --------
foote@p.cs.uiuc.edu (08/22/89)
It is possible to use doesNotUnderstand: to wrap code around a given Smalltalk object, but doing this seamlessly can be tricky. Problems arise because doesNotUndertand: is not invoked until after all methods defined for a given object have been considered for execution. This means that common methods defined by Object will not be passed to a Variable object's referent, but will be executed by the Variable object itself. An insidious scheme for circumenting this problem was described by Geoffrey Pascoe in an OOPSLA '86 paper on what he called Encapsulators. He created a hierarchy of objects that do not include Object as a superclass and hence respond to a minimal number of messages. As a result, nearly all messages can be intercepted using doesNotUnderstand: and forwarded to the Encapsulator's referent. This paper also describes how Pascoe dealt with the parts of the programmer interface that break when one creates objects like this. Another potential problem with the Variable object approach is that the wrapper will in effect stick to the value rather than the object owning the variable if references to the owning object's instance variables are not carefully controlled. That is to say, the approach being discussed creates active values rather than active variables. As a result, copies of the wrapped value with the wrapper still in place can "leak" out of an object. (Of course, for some applications, this may be just what is needed.) To create active variables, one must change the way that objects reference their variables so that messages like value and value: are sent to variable objects in place of explicit loads and stores. One way to do this is to modify the compiler to generate such code when appropriate. Were Smalltalk's scheme for accessing an object's representation an explicit part of its metalevel architecture then making selective modifications to it might be easier. Since the instance access protocol has largely been subsumed into the virtual machine, this is not the case. Brian Foote Dept. of CS, U. of Illinois @ Urbana-Champaign
eliot@cs.qmc.ac.uk (Eliot Miranda) (08/25/89)
In article <162@servio.UUCP> bruce@servio.UUCP (Bruce Schuchardt) writes: >There are some pitfalls in using proxy objects like this that you should >be aware of. The first is *speed degradation*. The second is *special >messages*. ..... >I would not recommend using this approach for compute-intensive applications. >In any case, it can be made most efficient by nilling out the superclass >of the forwarder class after it has been created. This is more work, but >you will end up with a faster forwarder. > >The second problem concerns special messages. You all probably saw the >message last week about the "value" method in contexts. In Smalltalk-80, >and evidently Smalltalk/V, some messages are treated extra special by the >compiler/interpreter. They don't go through message lookup, but are >trapped and executed immediately. Examples are "value" and "==". >ParcPlace Smalltalk-80 keeps a list of special selectors in a class >variable in SystemDictionary. YOU WILL NOT BE ABLE TO TRAP THESE >MESSAGES unless you change the compiler or recompile everything to use >different selectors. It isn't necessarily the case that you can't trap special selector messages in Smalltalk-80. he blue-book specification implements the == and class messages directly without a lookup. All other special selector messages are defined to workwithout a lookup only for specific class-selector pairs, e.g. BlockContext and value. Both PPS's Smalltalk-80 VM & my BrouHaHa Smalltalk-80 VM will only execute == and class for a small set of classes that are known and used by the VM, e.g. Array, Message, SmallInteger, MethodContext, True etc. At QMC we have used encapsulators for inter-machine communication & monitor objects (encapsulators that use a critical section to serialise message sends to the object they wrap up). The BrouHaHa VM also caches doesNotUnderstand: message lookups in the message lookup cache so that nopt every message that will not be understood will be looked up. (sounds complete gobbledegook I'm sure!) In summary, there is no reason why encapsulators should be a performance bottleneck. Almost everything can be optimised! -- Eliot Miranda email: eliot@cs.qmc.ac.uk Dept of Computer Science Tel: 01 975 5220 Queen Mary Westfield College International: +44 1 975 5220 Mile End Road LONDON E1 4NS