[self-interest] Objects with dynamic slots

Stefan Matthias Aust sma at netsurf.de
Sun Aug 29 14:31:46 UTC 1999


In Smalltalk, you'd overwrite #doesNotUnderstand, if you want an object
which understands messages to access something like slots you could define
at runtime. (Assume you can't use a compiler)

Object subclass: #Cluster 
  instVarNames: 'values'

doesNotUnderstand: aMessage
  | sel |
  sel := aMessage selector.
  ^values at: sel ifAbsent: [
    (sel argumentCount = 1 and: [sel first isLetter])
      ifTrue: [value at: (sel copyWithout: $:) asSymbol
                     put: aMessage arguments first]
      ifFalse: [super doesNotUnderstand: aMessage]]

In Self, you could probably do the same, but is there a better way to do
this?  Why should the VM bother looking up methods which we already know
don't exist.

I think, Ian Upright sugested something similar on comp.lang.smalltalk.
I'd like to customize method lookup, perhaps similar to this:

cluster _setLookupAgent: (
  | :mirror. :selector. slot |
  slot: mirror 
    slotAt: selector
    IfAbsent: [mirror parents "etc"]

The VM would then call the provided (anonymous) method object instead of
using its default algorithm.  You could even continue this idea and also
allow hooks for method and primitive execution.

A simpler way would be to have a special method, let's say

cluster _setGate: (
  | :selector. :arguments. |

which is called for every message that is directly sent to the cluster
object (which is also the receiver of that method).  While the gate method
is executed, it's disabled to omit recusions.  This could be implemented
with a simple flag for every object (a hidden slot to store that method (or
a well known slotname that's called from inside the VM)) and a counter to
temporary disable the mechanism.

Or is the SELF (actually mySelf, as I haven't looked up whether these
messages and primitives really exist in Self ;-) solution as simple as

cluster = (|
  parent = defaultBehavior.        "note, no parent slot!"
  values.                          "where to store the values"
  clone = (_clone values: dictionary clone).   "
  doesNotUnderstand: aMessage = (
    values at: aMessage selector IfAbsent: [
      aMessage delegateTo: parent] "forward message to parent"

This allows us to intercept even inherited messages - something which isn't
possible in Smalltalk.  The only problem is to hide "parent" and "value",
perhaps by renanming them to "hidden_parent" or "my_values".

Thank you for listening, I think I found the answer :-)
Stefan Matthias Aust  //  Bevor wir fallen, fallen wir lieber auf.

More information about the Self-interest mailing list