[Squeakfoundation]Method namespaces through multiple symbol tables

Jesse Welton squeakfoundation@lists.squeakfoundation.org
Mon, 4 Jun 2001 17:01:37 -0400 (EDT)


Stephen Pair wrote:
> 
> I think this is an idea worth experimentation.  My first impression is that
> it would create more problems than it solves.  If you pass any symbols from
> the code in one module to the code in another module, then use them as keys
> in identity dictionaries, you're going to get some un-expected results.

I'm not sure how often the results would really be un-expected.  Where
two modules want to use the same symbol in a given identity
dictionary, they will generally be related by module dependency, so
both will generally refer to the same symbol through the heirarchical
nature of symbol tables.

Alternatively, one could distinguish between symbol literals and
selector invocations, looking up all symbol literals in a global
context.  (This does, admitedly, require one to specify a selector
namespace for #perform: functionality.  That might prove to be
necessary, or at least desireable, with multiple method dictionaries,
too, though.)

> And, for the novice, they'll be very difficult to comprehend (and thus
> debug).

Yes, this is a likely problem.  I think multiple lookup dicitonaries
could produce confusing results along the same lines: "Why am I
getting a doesNotUnderstand, when I've defined this method?  Why is
this method being called instead of the version from my module?"

>  You also will not avoid having to re-do the development tools
> (imagine seeing two methods of the same name in the browser...which module
> does it belong to?  how do I compile a new method for a specific module?).

It certainly doesn't eliminate the need for reworking the tools.
Either way you cut it, the tools will have to allow the programmer to
specify which namespace you're working in, and for showing only the
methods relevant to that namespace.  For the most part, I think the
tools' interface could be much the same in both cases.

> I think the changes to implement this scheme would be no less difficult than
> the changes to implement it via enhancing the message look up and the method
> dictionaries.  It may work, but it's a little more obscure IMO.  If you've
> ever looked at the method lookup code, it's very straightforward.

I've not looked at it much.  Naively, I would guess the tools support
would likely take about the same amount of work, but the symbol-based
approach requires no work at the VM level.  Wouldn't making the method
lookup logic more complex add runtime overhead, too?  But perhaps I'm
completely wrong here.

> The tricky thing is not really the mechanism itself, but making it simple to
> comprehend.  The simple examples that have been discussed so far
> are...simple.  What happens in the case that your module imports another
> module that overrides a method?  Does your module use the overridden method,
> or the original one?  What if you import two modules that override the same
> method?  Which one do you use?  Do you allow a way to explicitly prefer one
> over the other?  Do you go by the order the modules were imported?

Hmm?  These exact issues exist with any implementation of method
namespaces.

>  What
> kind of complexity will this add to the method dictionary (now not really a
> dictionary but a more complex animal).  You're really adding a new dimension
> to the method lookup scheme.

No, I don't think this changes the nature of method dictionaries at
all, even conceptually.  It does change the nature of Symbols, though.
Symbols become attached to particular namespaces, so instead of simply
#someSelector, you conceptually have #someSelector-from-Foo.  (In
fact, Symbols could be extended with a namespace instance variable
that could be used by various tools.)

> We could probably come up with a simple rule (such as breadth first, import
> order), and allow some mechanism to override the default lookup sequence
> (kind of like "super" allows us to override the default lookup scheme)...but
> again, whatever it is, it needs to be simple for 99% of the cases.
> 
> How would a symbol based approach solve this problem?  Would it choose the
> symbol defined by one of it's imported modules?

I don't think it does solve the problem; but I don't see how multiple
method dictionaries does, either.  This is more a matter of the tools.
Generally, yes, the compiler would insert a symbol from one of the
imported modules, if it exists, or else would have a new one created
in the current module's table.  A symbol-based implementation could be
quite flexible in handling special cases, for instance by asking the
programmer which imported module's symbol to use in the case of
overlap.


Hmm, here's a possible problem case.

Core module:

  SomeClass>>meth1
    "do some stuff"
    self meth2.
    "do some more stuff"

  SomeClass>>meth2
    "do some different stuff"

Extending module:

  SomeClass>>meth2
    "some extended version of meth2"

Now, SomeClass>>meth1, when called from the extending module, won't
call the extended version of meth2, because it references the core
version.  While symbol-based modularity could in principle handle
calling the core meth2 from the extended meth2, I don't see how it
would possibly allow the core meth1 to call the extended meth2.

This situation could either be extremely rare (and bad practice), or
it could be fairly common; I don't know.  But if you can cite a place
where this structure is useful, and describe how a method
dictionary-based implementation of modularity could solve it, I'll be
sold.  Probably.  ;)

-Jesse