Hello, sorry this posting is so long ...
A while ago I asked if it was inconsistent that parent slots cannot be methods. There were questions about what this would mean, and why it might be useful, and also Mario Wolczko pointed out that it can already be done in the VM - with the behavior that if an object with a parent slot 'parent' was sent the message 'parent' then it would evaluate the method, and the object would inherit from the _method_object_ (*not* the object resulting from the evaluation of the method).
I 'stumbled' across a 'simply delightful' use of having parent slots as methods such that the inheritance is from the result of the method evaluation (OK - there are problems about what this might mean - but I'll try to explain what I mean)
If you are familiar with the use of 'data parents' then skip this paragraph. A useful 'pattern' in Self programming is using sort of 'wrapper' objects to add state/behavior to an object - e.g. if you have a point and want to give it a color and associated behavior, you could have a 'color wrapper' which has an instance specific assignable slot for the color, some suitable methods, and an assignable parent slot which is set to the point to which you want to add color.
A real problem with using 'data parents' is what to do with the slots that you would like to share between all 'wrappers'. If you put them in the 'wrapper' itself then there are problems of inconsistencies if you want to change them, and conceptually you have lots of copies of things that you really wanted to be shared, which is not a good thing (although maybe copyDown slots could be used to solve this problem). If you try to put them in a parent object of all wrappers (a different parent slot to the assignable one whose value is the wrapped object) then there are problems of ambiguous selectors and not being able to override slots of the wrapped object (unless you put lots of disambiguating methods in the wrapper object or modify 'ambiguousSelector:...')
The proposed solution to the above problem is to have a non-parent assignable slot in the wrapper to refer to the wrapped object, and a parent object shared by all wrappers, which itself has a parent slot which is a method which evaluates as the wrapped object. Therefore, all wrappers would share the same parent object, which could have methods overriding ones in the wrapped object; and there would be no ambigity problems, as the parent of the parent of each wrapper would be the wrapped object specific to each wrapper.
Madness? Maybe; but in case you don't understand/believe that such a thing is possible/useful, please try the example self code at the end of this mail. In this example there is a wrapper called 'wrapperExample' and an object to be wrapped called 'exampleWrappedObject'. Create a wrapped version of this object by evaluating 'wrapperExample copyFor: exampleWrappedObject'. Try sending this object messages 'aMethod' and 'aNonOverriddenMethod' and have a look at the code to see what's going on. Having a parent slot implemented as a method is faked by the parent of the parent of 'wrapperExample' by using delegation and 'undefinedSelector:...'. If parent slots could be implemented using methods then the method 'myParentWillBe' in the parent of 'wrapperExample' would be a parent slot.
Ivan (obfuskating on thin ice towards madness).
------------
'$Revision:$' ' Copyright 1992, 1993, 1994, 1995 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. '
'-- Module body'
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
exampleWrappedObject = bootstrap setObjectAnnotationOf: bootstrap stub -> 'globals' -> 'exampleWrappedObject' -> () From: ( | {} = 'ModuleInfo: Creator: globals exampleWrappedObject. '. | ) . } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'exampleWrappedObject' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
aMethod = 'the result of some method'. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'exampleWrappedObject' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
aNonOverriddenMethod = 'aNonOverriddenMethod'. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'exampleWrappedObject' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: InitializeToExpression: (nil)'
someAssignableSlot. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
wrapperExample = bootstrap define: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () ToBe: bootstrap addSlotsTo: ( bootstrap remove: 'comment' From: bootstrap remove: 'directory' From: bootstrap remove: 'fileInTimeString' From: bootstrap remove: 'postFileIn' From: bootstrap remove: 'revision' From: bootstrap remove: 'subpartNames' From: globals modules init copy ) From: bootstrap setObjectAnnotationOf: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | {} = 'ModuleInfo: Creator: globals modules wrapperExample.
CopyDowns: globals modules init. copy SlotsToOmit: comment directory fileInTimeString postFileIn revision subpartNames.
\x7fIsComplete: '. | ) . } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot\x7fVisibility: public'
comment <- ''. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot\x7fVisibility: public'
directory <- 'applications'. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: InitializeToExpression: (_CurrentTimeString)\x7fVisibility: public'
fileInTimeString <- _CurrentTimeString. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
postFileIn = ( | | transporter moduleDictionary resetFillingSemaphore. snapshotAction addSchedulerInitialMessage: message copy receiver: transporter moduleDictionary Selector: 'resetFillingSemaphore'. resend.postFileIn). } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot\x7fVisibility: public'
revision <- '$Revision:$'. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'modules' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot\x7fVisibility: public'
subpartNames <- ''. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
wrapperExample = bootstrap setObjectAnnotationOf: bootstrap stub -> 'globals' -> 'wrapperExample' -> () From: ( | {} = 'ModuleInfo: Creator: globals wrapperExample. '. | ) . } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
parent* = bootstrap setObjectAnnotationOf: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> () From: ( | {} = 'ModuleInfo: Creator: globals wrapperExample parent. '. | ) . } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
aMethod = ( | | resend.aMethod,' with something added'). } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
copyFor: x = ( | c. | c: _Clone. c wrappedObject: x. c). } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
myParentWillBe = ( | | wrappedObject). } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
parent* = bootstrap setObjectAnnotationOf: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> 'parent' -> () From: ( | {} = 'ModuleInfo: Creator: globals wrapperExample parent parent. '. | ) . } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> 'parent' -> 'parent' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: FollowSlot'
undefinedSelector: s Type: t Delegatee: d MethodHolder: m Arguments: a = ( | | s sendTo: self DelegatingTo: myParentWillBe WithArguments: a). } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: InitializeToExpression: (nil)'
someWrapperAssignableSlot. } | )
bootstrap addSlotsTo: bootstrap stub -> 'globals' -> 'wrapperExample' -> () From: ( | { 'ModuleInfo: Module: wrapperExample InitialContents: InitializeToExpression: (nil)'
wrappedObject. } | )
'-- Side effects'
globals modules wrapperExample postFileIn
self-interest@lists.selflanguage.org