A little namespace "proposal"

Andreas Raab andreas.raab at gmx.de
Wed Apr 7 00:12:10 UTC 2004


Hi Goran,

After reading your proposals and the responses to it I'm starting to realize
how right Jecel is when he says that we look at the term "namespace" from
entirely different points of view. Bear with me for a little, because I
think I need to explain this.

When I use the term "namespace" I refer to something that integrates more
than it separates - I actually want namespaces to provide people with a
concise and clean set of names so that they can easily identify what they
want from within that context, while -at the same time- force them to be
explicit when they violate the "meaning" implicit in that context. So, for
example, "name conflicts" are something that doesn't really matter all that
much for me simply because a "name conflict" occurs if there is an existing
concept that you may collide with. And would I want it to be easy for you to
actually create such a collision of concepts? Hell, no! If there is a
ScrollBar in Morphic the user should have to go through some pain before
he's allowed to introduce a *different* concept under that same name. So in
this sense I agree with you that "name conflicts are helpful".

However, when we look at "alternative implementations of the same concepts"
such as Morphic vs. MVC vs. Tweak as UI frameworks or Squeak's streams vs.
Flow there are conceptual conflicts which should make it very hard to "reuse
a name from a conflicting concept". Say, if I write a Morphic app and I just
happen to use the name "Switch" which is NOT defined in Morphic but IS
defined in MVC I should not be able to do this because although there *may*
be a class called Switch it is not part of the context I am working in -
there is no working "Switch" class in the context of Morphic so allowing
users to use that name is simply introducing confusion. Similarly, just
because Flow may not have a class called "WriteStream" doesn't mean that you
should mix up the concepts - if Flow says it captures the concept of
streaming and other IO, then clearly the use of "WriteStream" in the context
of using Flow is just a complete confusion of concepts and should be avoided
at all costs.

(BTW keep in mind that I see the context as something that is VERY dynamic -
in fact I would argue that if you open an MVC project instead of a Morphic
project your context should be different and so should the names you see)

So, to me, a namespace isn't about "my little box" as much as it is about
"my larger context". That's important because as you can see from the above
it is absolutely required to "block" names that originate from "conflicting
contexts". Meaning that the mere requirement of "never specify anything that
doesn't need explicit specification" is not good enough for me here - it
leads to conflicts in random places and actually makes things worse. I'd
rather use prefixes (which I am today) than to introduce that kind of
conceptual confusion.

That's for the way I'm looking at namespaces - I have no idea if the above
clarifies things enough, but really we have a fundamentally different idea
about what a namespace is (which is okay - it doesn't mean we can't agree on
an implementation that serves both points of view ;-)

That said, let me alse point out a few bits of history. I don't remember if
you were present in the late 3.3 modules discussions but one of the things I
tried was to at least get namespaces to work properly. I utterly failed -
and it wasn't because there would be too much code involved, it was because
the modules were overloaded with responsibilities, doing too many things at
once, interacting weirdly. That's my major motivation for saying "keep them
simple" - if you look at the discussions so far, you can see there are
simply too many things all over the places that are being discussed which by
the end of the day would lead to desastrous monster if we would try to
implement everything in a single place.

So what I am fundamentally looking for here, is a namespace implementation
which can "serve my needs" while being able to (now or later) serve someone
else's needs (such as for packages and similar). That's the reason why I
really don't want to get mangled up in the discussions about packages - they
simply aren't my needs or goals.

I'm saying this, because I look at your proposal from the point of view of
"would I be able to do what I want to do?" rather than assessing "is this
what the Squeak community should adopt for managing package namespaces"?

> - Instead of having one big bag of globals (Smalltalk) we have a a
> number of Namespaces. A Namespace is just a Dictionary of associatons
> between names and objects like Smalltalk, and the Namespaces aren't
> related to each other in any way - we just have a flat list of them. So
> typically we have say these Namespaces (which I will use in the rest of
> the post as examples) and many more:
>
> Kernel
> Collections
> SqueakMap
> Seaside
>
> (note how I have made this a bit coarser than the categories - of course
> the actual partitioning is open for discussion, but just bear with me
> for this post)

I like the granularity - it is one that I would have chosen similarly
because they seem to be oriented on "concept groups".

> - When creating a class in a class category the template would look
> like:
>
> Object subclass: #NameOfSubclass
> instanceVariableNames: ''
> classVariableNames: ''
> poolDictionaries: ''
> category: 'Kernel-Processes'
> namespace: 'Kernel'

This I don't like very much as I think the context in which you are working
in should be implicit for the most part. The extra namespace specification
makes it even harder for people to deal with class definitions so if we were
following that path I would most definitely opt for an "automatic namespace
creation" based on the category.

> - There is no explicit "creation step" for a namespace (or removal) -
> they are simply created and removed "on demand" or whatever. This means
> we all can "carry on just like before". :) Or in other words, it is an
> attribute of the class.

This I really don't like because (to me) it feels like the creation of
"little boxes" instead of "large contexts". So the creation of a namespace
should be something I do quite deliberately because I set a new context.

> - When writing code you can refer to the class Delay in two ways -
> "Delay" or "Kernel::Delay":
>
> 1. If you type in "Delay" then we first look in the local Namespace of
> the class you are editing. If there is a "Delay" in that namespace then
> we bind to that. If not, then we look in ALL other Namespaces and if it
> resolves in none we signal an Exception. If it resolves to one we ask
> the user to confirm the right binding. The source will still read
> "Delay" but the binding is still in itself fully qualified as
> "Kernel::Delay" since it is in fact an object reference to that class.
> If it resolves to more than one, the user gets to choose which one and
> it will be expanded to "Kernel::Delay" in the source (if that is the one
> he/she chooses).

This I dislike too, but on the grounds of consistency and it is also why I
like imports. The only rule for qualifying names for me is: If I see an
unqualified name, it exists in my namespace. Period. Otherwise I need a
qualified name. This approach partly depends on the "large context" point of
view because I agree that otherwise it would lead to endless imports and
qualifications which would only be annoying.

Also, note that the above fundamentally violates the "avoid conflicting
concepts" rule that I mentioned above - it is the precise point of what I am
talking about that using the name "Switch" in the context of a Morphic
project should NOT, NOT EVER, resolve automatically to the MVC class
Switch - someone who really "means" to use that MVC switch should have to
state that he is "leaving the concept space of Morphic" by writing
MVC::Switch.

> 2. If you type in an explicit reference "Kernel::Delay" then the
> Compiler (or whatever) first checks for the Namespace "Kernel" and if
> that exists looks for the name "Delay" in it. If it isn't resolved then
> an Exception is signaled and the Browser should look through all other
> Namespaces for "Delay" and if found - ask if it should be corrected. If
> there is only one Delay in the system to find, then it can be corrected
> to "Delay", otherwise it will be corrected to the fully qualified form.

Again, I'm having a problem with this in terms of consistency. I would
expect that I either have Delay in my namespace or not. If I have, I use it
unqualified, if I don't I need to qualify the name. One of the problems here
is the inconsistency between me writing

    Kernel::Delay. "exists, no correction"

and

    Frobler::Delay. "gets 'corrected' to Delay"

This seems like a potentially confusing way to refer to the same object.

> - When a new class "SqueakMap::Delay" is created the tools should warn
> me that there already is a class called that in another Namespace and
> that it is generally better if the classes don't conflict by name
> because of the way resolving works. Sure, currently (before we get a
> superserver somewhere that can do lookups globally) this only checks
> against my current image but should still be useful.

Here again, it depends on whether the namespace represents a conflicting
concept or not. If I define a "Switch" in Morphic there is no reason why the
tools should even bother to say anything. There simply is "no Switch in
Morphic".

> Ok, enough for now, cutting this short so that Avi get a chance to read
> until he falls asleep. What do you all think?

I think that ultimately I could "almost live with that proposal" except for
the issue of automatically getting names from namespaces which describe
conflicting concepts. That is the one thing that definitely won't work for
me.

Other than that I see some problematic issues for purposes of packaging
(say, loading code which use the abbreviated name into a system which has
more than one interpretation for the same short name) but a) there are some
trivial solutions merely by actually using "implicit imports" (when you get
to the guts of it, I think you will find that implicit imports are in fact
advantageous to a universe-wide lookup whenever you get some code from
somewhere ;-) and b) like I said this isn't in my focus so I'll happily let
you do what you'd like to do.

Cheers,
  - Andreas




More information about the Squeak-dev mailing list