Namespace and Module Discussion

Les Tyrrell tyrrell at iserve11.lis.uiuc.edu
Sun Feb 3 05:04:06 UTC 2002


----- Original Message ----- 
From: David Simmons <David.Simmons at smallscript.com>
To: <squeak-dev at lists.squeakfoundation.org>
Sent: Saturday, February 02, 2002 4:23 PM
Subject: RE: Namespace and Module Discussion

> In that vein, let me sally forth with a few comments:
>
> For a variety of reasons (presumably to be uncovered in subsequent
> posts) the following rules hold in SmallScript:
> 
> a) Classes [class/metaclass pair as a unit] are binding-scopes
> (namespaces); most frequently referred to as "scope(s)". The class pool
> holds the variables.
>
> c) Modules are classes. Which implies a lot of things... Not the least
> of which is that modules can have unique behavior, and offer runtime
> scoping as a separate aspect/notion available within single unified
> object's capabilities.

This has been proposed before for Squeak, originally ( AFAIK ) by Peter Novak, who had ported this from VW 3.0 where it had been done by Augustin Mrazik.  I've also heard of several other proposals along those lines.  But I've never understood why this sort of choice would be desireable - to me, it seems that a module already has plenty of other things to do in taking care of business, without also trying to act like a class.  Here you are mentioning that it has some advantages in being able to provide what appears to be instance-specific behavior to a particular module.  I suppose that being able to add behavior on a per-module basis would provide the greatest possible flexibility, but really how much of that is actually required, and if this is really an overly restrictive attitude on my part, what option other than making the module be a class would be available?  To me, modules are not classes.  They are not system dictionaries, either- I think both choices are incorrect as a model for what a module should be.  At first blush, I don't think that modules should be able to "instantiate", thus should neither act as object factories or as object structural templates, or act as method repositories for other objects, all of which are things that only classes do.  However, it seems to me that if you believe that modules should have instance-specific behaviors, then this can be accomplished without also carrying over the burden of all the other things that classes do.  So, in a sense perhaps what you are reccomending is that a module should have *some* Metaclass-like behavior, ie, being able to define its own behavior in a totally self-contained and self-referential manner?  Certainly there is precedent in the image for at least one object that does that sort of thing already.

> d) Interfaces are classes. Lots to say here, but that would be a
> tangential discussion.

Again, are we talking about things that are going to instantiate?  It seems to me that interfaces would not instantiate, but perhaps that is again an overly-restrictive view on my part.  I've never envisioned them as being anything more than a way to describe, independent of clients and providers of certain "services", what those services are.  Thus I would not expect Interfaces to define method implementations.  So, I don't see the benefit in having Interfaces also be classes.

> e) All runtime-binding-scoped elements are "owned" by one (and only one)
> module.
>
> f) Modules are units of packaging/deployment. A "module" partitions
> deployment/loading of resources (including classes and methods). A
> "module" represents a "unit of packaging/deployment" for
> structuring/organizing availability of resources (including classes and
> methods).
>
> g) A "scope" is a "unit of priviledge" which partitions runtime binding
> of variables and behavior.   a "scope" [sometimes referred to as a
> namespace, but best referred to as a binding-scope] represents a "unit
> of priviledge" for runtime access-permission to "something within that
> scope".

> i) Scoped methods (via selector namespaces) enable partitioning
> (scoping) of code changes within a given class. Remembering that by rule
> (e), all methods are owned by one, and only one, module.

> j) Symbols are scoped. Every symbol consists of a common selector name,
> and a scope (as defined in (a)).

I can see where this would make it very easy to avoid conflicting definitions as multiple modules attempt to define the same method in the same class at the same time- If my understanding of this is correct, then for each module defining a method for a class that it does not itself define ( that is, a class "extended" by these modules ), there would be separate methods entered into that class's method dictionary, each selected by a Symbol which would have the same textual representation ( perhaps even the same canonical Symbol as representation ), but which would in fact be a different Symbol for each selector ( ie, one that might otherwise be printed as #ModuleA::doSomething or #ModuleB::doSomething, both of which are incarnations of the canonical Symbol #doSomething ).  This is ( or should be ) possible because Symbols are objects, and this is actually all that the VM knows about them- so any objects can be used as selectors, including slightly more complex ones that are aware of both the module in which they are being used and the canonical symbol that they represent in that module.

What is not clear to me, is how ModuleA would refer to methods defined in other modules.   For example, collection methods like #do: or Boolean methods such as #ifTrue: .  These might actually have selectors known as #Base::do: , so how would methods in ModuleA invoke methods through these other selectors, defined for instance in Base? Or is it possible to implement selector namespacing without modifying the VM in some fashion?  What I don't see is how methods compiled using the Symbols from one namespace will readily invoke methods compiled using the Symbols of a different namespace.  In Oasis I've been fairly successful at isolating things, but haven't put as much effort into recombining them.


[ slightly re-arranged ]

> b) Types for FFI and the optional type system, are classes. This implies
> lots of things... Not the least of which is that you can write the FFI
> marshalling code as methods within the class.
> 
> h) Modules are assembled (packaged) as COFF/ELF/CodeFragment files by
> default [this offers innumerable benefits]. Where a COFF/ELF file may
> contain 0 or more modules. A pure module with no resources or externally
> compiled C/C++/Asm code is a self describing blob (and so can be
> packaged in any form desired). Any resources or and methods exported as
> callback entry points, are exposed directly through standard OS platform
> COFF/ELF/CodeFragment facilities.

> Given the above rules a system can be automatically sliced and diced
> into discrete shared-libraries (modules). Where a shared library can be
> loaded or unloaded on demand and offers native operating system program
> access to resources and exported entry points, digital certificates,
> etc. 

It appears that these items have much more to do with Smalltalk inter-operability with other languages, and that  you are going significantly beyond merely having a modular Smalltalk, to one that is also inter-operable with "modules" written in other languages.  My own aims were quite a bit lower than this- I just wanted to have control over the composition of my own image.  I'd actually be quite happy if that were all that were achieved.  However, if this additional capability is also within reach then certainly it is worth considering.

> The shared-library mechanism is possible because all of the
> environment/image changes a module makes are known through the "module"
> ownership rule(e). And because the selector-namespace rules for
> scoped-methods ensure that changes made to a common class, by different
> modules, are distinctly identified by rule(j).

Hence cross-dialect Smalltalk inter-operability ( as a subset of cross-language inter-operability ) , if we get it right?

- les





More information about the Squeak-dev mailing list