[ENH] Symbol Spaces

Stephen Pair spair at advantive.com
Fri May 10 21:11:59 UTC 2002


Yes, your (Allen Wirfs-Brock's) paper does a much better job of
explaining it.  I would have liked to have seen an example that dealt
with the issues of class extensions a little more closely.  The security
example seems less useful to me.

Let me re-iterate what symbol spaces is and is not:

  It is:
    - a refactoring of String and Symbol to allow subclassing those
protocols
    - a refactoring to replace the global symbol table code with the
SymbolSpace and GlobalSymbolSpace classes
    - the introduction of LocalSymbol designed to work with an instance
of SymbolSpace
  It is not:
    - an enhancement to the module system
    - an implementation of selector spaces
    - a change to the compiler or vm

To me, this code represents something that is digestable and feels right
without getting into the thorny issues of modularization.  In other
words, it's an enhancement that could allow for experimentation in those
directions, but doesn't itself do anything in those areas.  I definitely
like the fact that the symbol table management is handled by a class
(instead of a collection class side methods), and that it's possible to
have more than one of them.

Now, getting back to the fun topic of "Selector Spaces" and
modularization:

Allen said:
> My major reservation about this approach has always been a 
> concern about 
> understandability and usability. While the distinction 
> between a name and 
> its binding as normal and obvious for compiler writers like 
> me it's not so 
> clear that the distinction is all that obvious to many Smalltalk 
> programmers.  Symbol==method selector==method lookup key is a 
> nice concrete 
> concept that is easy to explain. Adding the extra level of 
> indirection 
> probably add an "order of magnitude" to the conceptual 
> complexity of this 
> part of the language.

As someone famous once said, you cannot remove complexity, you can only
shift it from one place to another.  We deal with this complexity
everyday.  Anyone who's ever tried to maintain a significant body of
code in Squeak from one version to another knows this complexity.  So
too the people who've tried to strip the image down to some fundamental
core plus their application.  The trick is to relieve our brains of this
burden and design an environment that handles this complexity for us.

I believe that this issue can be tackled without any loss in
understandability or usability.  It will take a combination of
meta-model changes, potential vm changes, and tool enhancements.  And,
the tools are very important.  The example I like to give to illustrate
this fact is that it's possible to develop code in Smalltalk using only
inspectors.  However, being successful in developing software in that
way would require that you cope with an enormous amount of complexity.
The point is that the class browser (a tool) is much more effective at
conveying the underlying structure of the Smalltalk meta-model than the
inspector.  Thus, the tools are very important (which btw, is a point
that shouldn't be neglected when thinking about how to make the modules
more usable too).

Now for some gory (but fun) implementation stuff.  A thought recently
(last few hours) occurred to me about binding selector names to selector
values with the compiler.  I was thinking through the issue of local
symbols masking out global symbols.  The issue is that I would want the
compiler to generate local symbols in some circumstances, and globals in
others.  One way to solve this is to introduce new syntax (ick).
Another way is to only generate locals when the local is defined in the
current module, or in an imported module (or one of the imported
modules' imported modules).  However, the later solution has the
following problem:

  Suppose that ModuleA extends OrderedCollection by adding a new #add:
method.
  This new method is entered in the method dictionary with a local
symbol.
  Now suppose some code in ModuleA sends the #add: method to a
LinkedList.
  The compiler compiles in the local symbol for #add:.
  LinkedList is not a subclass of OrderedCollection.
  MessageNotUnderstood!

The thought that I had is that rather than compile in a direct reference
to a selector value, we instead compile in an Array of selector values
ordered from most preferable (the local selector) to least preferable
(the global).  Method lookup in the VM would be altered to accommodate
the new lookup semantics and the global #add: would be found for the
LinkedList.

Now for a slight complication.  A subclass of OrderedCollection has
overridden the #add: method (in the global symbol space).  What do we
do?  A) invoke the global version of #add: for the subclass (knowing
that a super send in that method would not invoke our local #add:
method) or B) invoke the inherited local #add: without regard to the
subclass' global #add:?

My sense is that B is the more correct thing to do if you provide a
facility to explicitly invoke the global version of #add: from within
the local implementation of #add: and if the tools can alert you when
you're localizing an existing method that has global overrides in
subclasses.  This is the area where tools can make all the difference in
the world.

(The interesting thing is that none of this complexity being discussed
is new...we all deal with these issues anytime we attempt to merge or
migrate code...we just don't have a framework for understanding and
managing this complexity)

- Stephen




More information about the Squeak-dev mailing list