A little namespace "proposal"

goran.krampe at bluefish.se goran.krampe at bluefish.se
Wed Apr 7 09:50:20 UTC 2004


Hi Andreas!

Note - I have been thinking some more yesterday and may have refined my
understanding of my own proposal. I have a new writeup - equally messy
perhaps - but I think more exact. :) I will try to condense it, but
first it would be interesting to see some replies to this one. Sure, it
is long - but it feels like this is getting somewhere.

anyway...

"Andreas Raab" <andreas.raab at gmx.de> wrote:
> 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.

Sure. I am 100% patience. :) And in a good mood today.

> 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".

Ok, all in agreement there I think. :)

> 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.

Ok, I interpret this to mean that you don't think we should allow to
"render" Kernel::Delay as just "Delay" even though there is just one
class Delay in the image. But I will read on...

> 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.

Ok, so you are simply saying that short-form is a no-no, unless for
local names.
That will force the use of imports to make the code readable. Sigh.
 
> (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)

Eh... hrm. Not sure I follow.

> 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.

Hmmm, how can it lead to conflicts in random places? Not sure I
understand that.
But perhaps you just meant "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 ;-)

True indeed. :)

> 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.

I agree - even though I think my "little proposal" is quite simple. :)

No hierarchies of namespaces - just a flat list, always storing all
references in the source as fully qualified names, rendering them in
short-form and accepting short-form only when it can't be misunderstood,
each class belongs to one namespace, possibly allowing "shyness" to keep
the tools non-annoying. All in all, very simple IMHO. :)

> 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.

Fine. I am trying to see this from your view too.

> 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"?

I know - and I have also tried looking at it from your POV. :)

> > - 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.

That would make category == namespace. And that would make PI ==
namespace - which I am not sure is so great. But hey, a minor detail I
assume. Avi will surely post his opinion. :)

> > - 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.

Ok, well - I have been thinking about that. Will we have objects
representing the namespaces?

Avi's proposal of simply having all fully qualified names in Smalltalk
would imply we really don't need to create such objects. But intuitively
I feel that, hmmm - it is just a matter of time before we need a Real
Object. Just look at PI, same thing happening there IMHO.

So ok - we can create Namespace objects but we could let the tools do it
"automatically" so that the illusion to the developer is the same.
Agreed? Then of course I assume you want to put those Namespace objects
into Smalltalk and then have the local bindings in itself so that:

(Smalltalk at: #Kernel) at: #Delay) == Kernel::Delay

Right? Avi wanted us to just keep all entries in Smalltalk - so should
we do both? I don't know. Thoughts? Sure, implementation details - but
it makes these things easier to grasp.

> > - 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.

You know - how the references are rendered can be a Preference.
Seriously. :)
So if you want all non-local references to be fully qualified you can
get it.

But you will of course drown in Kernel::Array,
Collections::OrderedCollection etc, unless introducting imports - which
I truly dislike.

But see the end for a tweak (no pun intended) to my proposal that might
make you happy.

> 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.

Oh, here is obviously an important point that I am missing. What is in
fact the "large context" POV that prevents the endless
qualifications/imports? Must have missed something.

> 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.

Hehe, I could turn your own "weapon" against you and say that - hey, its
a tool thing.
I mean, I can use the alternative syntax or whatever - you can't stop
me, can you?
So I can use my "render as short form and accept short form when it is
unambiguous"-mechanism if I want to. :)

This is all based on the fact that all references are stored in the
source *fully qualified*. So what we in fact are arguing about here is
the "tool support" I think. See end of this post.

> > 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.

Eh... let me correct my own ramblings here - my original post was a bit
flaky I think.
Let's presume there is only one Delay in the whole image, Kernel::Delay.

Then I am proposing that I can type "Delay" or "Kernel::Delay" and in
*both* cases it will be rendered as just "Delay" when accepted. But in
the source (only visible in fileouts, in the changes file etc) it will
always be full qualified as "Kernel::Delay".

Yes, you are correct that seeing "Delay" in the browser method pane can
mean two things:

1. Either there is just one Delay in the system, God knows where. :)
2. Or it is a local binding in the namespace of the class.

I find that little possible "confusion" a small price to pay in order to
get rid of imports. :)
We could of course play with the thought of making these two situations
render slightly different...

> > - 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".

And this is *exactly* what I am talking about - you are arguing for a
model that is AFAICT exactly like in Java. I want it to *hurt* if the
developer creates names that already exists in other namespaces - at
least I want him to know it and have to do something about it.

In short - you are promoting a pessimistic model, and I want an
optimistic model. You want to prevent all conflicts by making fully
private boxes - and I want to "embrace conflicts" and deal with them
when they occur by creating largely transparent boxes.

> > 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)

No, as Avi explained further - there will be NO short forms in the
actual source Strings. Only fully qualified nams. That is an important
aspect here, very important. I want to preserve as much information as
possible from when the method was compiled and thus the reference was
resolved, in the source.

Sidenote: In fact - we could use some similar scheme for class vars.
Remember the "shadowing"-thread a while back? Same issue I think.

> 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

I will get back with a different writeup in which I will try to make
some things more clear and possibly tweaking the proposal so that it
handles the "no Switch in Morphic" thing. In short (he, didn't turn out
very short...) it will go something like this:

When you look at code in browsers, and when you accept code into the
browsers - Squeak should be helpful. And there is no reason why Squeak
can't behave differently based on Preferences. The end result in the
code will always be fully qualified names anyway, so how we get there -
and how the source is rendered in method panes - can be viewed as simply
*A Tool Issue*. Right?

As Avi cleverly noted the important points in my proposal are:

1. All references will end up fully qualified in the source code. No
short names. Not even inside the namespace itself IMHO.

2. How we render code in the method panes can be viewed as a tool thing.
We alread have pretty printers, alternate syntaxes etc. Why not
introduce a "filter" that abbreviates references according to
Preferences?

3. How something I typed is turned into a fully qualified name is *also*
a tool issue. The browser can ask me questions etc. This can *also* be
according to Preferences!

So, Andreas could use a Preference which only render local names in
short-form, and only accepts those names in short form. He could also
introduce some global "import list" that is used to allow additional
short names from certain namespaces etc, like from Morphic, but not from
MVC.

That would solve the "no Switch in Morphic" issue, wouldn't it?

Cheers, Göran



More information about the Squeak-dev mailing list