[Modules] Upper case message names for accessing modules

Henrik Gedenryd h.gedenryd at open.ac.uk
Mon Feb 25 09:02:27 UTC 2002


goran.hultgren at bluefish.se wrote:

> without any neighbor modules. So ok, I need to do it explicitly, I ran
> the "self deepDeclareExternalRefs." from the explorer-thingy and then
> BAM, it added two neighbors:
> 
> #(Squeak Language Core)*
> #(Squeak Language Collections)*)
> 
> I am not sure why it didn't go all the way down to Streams... Even
> adding a reference to ReadStream didn't make it go there. It actually
> seems that these two modules are always neighbors - even with an empty
> method!
> 

The modules Language Core and Language Collections import all their
submodules, including ReadStream.

> hopefully Squeak will "auto
> import" a module during compilation - at least if there is only one
> module active that does define that name. Henrik?

Right. This is what deepDeclareExternalRefs does. But automatic declaration
is not really an option, your module dependencies really describe the
"organizational logic" of your code, which isn't evident from the names you
use.

For example, if your module uses Balloon3D heavily, the auto-declarer will
add, say, dependencies on five or more submodules of Balloon3D instead of a
single one to the Balloon3D module, which would be the logically right thing
to do. (Balloon3D then ought to import its submodules so you only need to
declare a single dependency on that module.)

An auto-declarer can never discover that this is the "correct" higher-level
logic behind your code, because sometimes you may want to import exactly two
of the B3D submodules instead of all of B3D or whatever.

> 1. Imports are made on module level. We already have that - the neighbor
> modules. I think.
> 2. If you type a direct reference in the code it would generate an
> automatic neighbor module reference on compile. It would of course barf
> if that module is not loaded (it doesn't have to be active, right?).
> 3. If you type a non direct reference like "EllipseMorph" then I would
> like it to:
> 1. If there is already ONE and ONLY ONE neighbor module exporting
> EllipseMorph then do nothing. All is fine.
> 2. If there are two or more neighbor modules exporting EllipseMorph
> then barf and ask user to make a direct reference using whatever
> syntactic means there are for that. :-)
> 3. If there are no neighbor modules exporting EllipseMorph, find it
> among all loaded modules and if there is ONLY ONE - add that module as a
> neighbor. Ask user for confirmation. This could be a Preference.
> 4. If there are more than one loaded module exporting EllipseMorph, ask
> which one should be added as a neighbor.

This sounds like a very good solution.

Now, as you noted, there still is the odd case when you need to specify in
your code exaclty what module to pick a name from, e.g. where there is a
name conflict (perhaps Component is more likely to have a conflict than
EllipseMorph though!)

Like David S. noted (and Les did last fall), giving the full path inside
your code is brittle. So I fully agree,

ellipse := Squeak Morphic Core Basic EllipseMorph new.

is not a great idea. That is why you can use aliases for external modules,
e.g. you'd declare that your module depends on #(Squeak Morphic), and that
this module should have the alias Morphic inside your module.

so in the dependencies (the "interface" of the module):

    ... externalModule: #(Squeak Morphic) alias: #Morphic ...

and in your code,

    morph _ Morphic Component new

to distinguish it from the Component class in the super-meta-reflective
programming code you also depend on:

    ... externalModule: #(Project FancyMetaProgramming) alias: #MetaSystem
...

    model _ MetaSystem Component new

I think this is acceptable, even probably preferrable to other solutions
IMHO.

On the same note, using prefixing, i.e. always using Morphic Component
instead of just Component, probably leads to less brittle code, since you
are always explicit and clear about where you are taking a name from. Just
"blindly" using imported names from all over can lead to really confusing
bugs.

If people don't want to have to declare aliases all the time, then the name
of the last module in the path could be allowed as a default, ie. #(Squeak
Morphic) would allow Morphic as an alias by default, but perhaps that is not
worth the potential confusion.

> But it sounded as Stephen wa talking about having "the old" references
> still point to the "old" name but the new ones (after having added the
> extra neighbor) point to the new name. Uahh! That sounds SCARY to me.
> How would I know what it points at by reading the code? Perhaps I
> misunderstood.

It would also cause recompilation to fail, so it wouldn't work in practice.

> Unfortunately, an
> implicit reference will not work when loading the module into a fresh
> image (how would we know what module to bind it to?  And, we don't want
> to prompt the user at load time).  Implicitly binding based on the order
> of the modules would be tricky and obscure as well.

Yes, you couldn't be allowed a choice between different bindings for the
same name, you'd always have to use the first one given by the order of your
imports. Otherwise loading or recomp. would fail. Or each Squeaker loading
your module would have to specify which binding you intended your code to
have. ;-)

Lex Spoon wrote:

> Modules @ #Morphic @ #Core @ #Basic @ #EllipseMorph
> 
> Now you can look up #@ and see what is happening, where before you had
> to lookup up #doesNotUnderstand:.

Here, it would translate to

    model _ (Morphic @ #Component) new

which I think would be acceptable (but one must remember to use parentheses
for this one). But beginners are likely to be confused by the # here, since
they already are puzzled by having to use #SubclassName when creating new
classes. So I don't think there is a "perfect" solution to this.

Stephen Pair wrote:

> Regarding the issue of importing a new module that has a duplicate
> export of a symbol that's already being used...maybe the solution to
> this problem is to enhance what the compiler is producing.  Rather than
> compile in references directly to an association, maybe we should
> compile in a reference to something a little more sophisticated...if we
> change the VM such that the #value method is actually sent (rather than
> make an assumption about having an association), this should be an easy
> thing to achieve (and it's arguably the right thing to do regardless).

This is propbably what Dan had in mind with the uppercase message mechanism.
"Morphic Component" will actually send a message to the value of the Morphic
binding, causing this lookup, like you suggest (if I understoood you
correctly). And this with no special machinery. No recompilation needed if
the binding of the alias Morphic changes.

Also, someone suggested that we automatically would compile in methods that
would return the variable value, instead of using doesNotUnderstand: like
now. 

> On another note, regarding the upper case convention, what happens for
> lowercase modules names?  Like "People svp"?  Would we need to make the
> people modules upppercase?  Like "People Svp" or "People SVP"?

Note that this is just a special convention for accessing names defined in
modules (which may be their submodules, or globals, but typically classes).
So the message selector is identical to the accessed name. So if you would
deviously force your module to define the global "myGlobal" (non-uppercased)
then "YourModule myGlobal" would be the message to access it.

> I actually just encountered such a situation when trying to load the
> ModuleTool...it requested version 0.0003 of the module code and wouldn't
> load because I had 0.0004...even though the tool seems to work fine when
> I modified the def file to require 0.0004.

Yeah, it is still waiting for someone to implement a real versioning system.
<hint> But the warning dialog could be better I think.

Actually this is a meta-level check, to ensure that the module code will be
able to understand the definition format used in the file. Any refinements
to the very crude current check are warmly welcome.

Henrik

> 
> Well, whatever, perhaps I am "out bicycling" as we say in Sweden. :-)

Note to non-Swedish speakers: Göran's Swenglish is hilariously funny if you
know the expression in question!




More information about the Squeak-dev mailing list