import concerns (was Re: Historical language survey)
kris
foo at bar.com
Fri Jul 7 15:33:39 PDT 2006
to clarify, here's some examples:
--------------
module foo;
import bar;
import wumpus;
extern (C) int printf (char*, ...);
class Bar {char[] toString() {return "foo.Bar";}}
void main()
{
auto bar = new Bar;
auto wumpus = new Wumpus;
printf ("%.*s\n", bar.toString);
printf ("%.*s\n", wumpus.toString);
}
-------------
-------------
module bar;
class Bar {char[] toString() {return "bar.Bar";}}
-------------
-------------
module wumpus;
class Wumpus {char[] toString() {return "wumpus.Wumpus";}}
-------------
What's interesting here is the lack of conflict between bar.Bar and
foo.Bar. The compiler ignores the conflicting names and uses foo.Bar
within main().
Now, assume both modules foo and bar are from different vendors. Module
bar gets changed at some point to this:
-------------
module bar;
class Bar {char[] toString() {return "bar.Bar";}}
class Wumpus {char[] toString() {return "bar.Wumpus";}}
-------------
The vendor added a Wumpus class to the module. Quite innocent. In this
case, the program now fails to compile, and the user-code needs to be
re-engineered. The amount of redundant work may be small, or it may be
very large. This is simply redundant work ~ it should not be necessary
at all.
One way to avoid the re-engineering is to use
"import wumpus as ...."
"import bar as ...."
In this case, the instances of Bar and Wumpus must be fully qualified --
you can't access them any other way. Thus it would be "auto bar = new
bar.Bar;", or whatever.
Another approach is to import explicitly, just like Modula-3 does:
import Bar from bar;
import Wumpus from wumpus;
In this case, it's pretty clear than any additions to modules from
either vendor will not result in re-engineering work. It's also a bit
closer to the current D model.
Another question is this: why is there no conflict between the two Bar
declarations in the first case, while there is between the two Wumpus
instances in the second case? I suspect this is down to where the decl
actually resides (which module).
kris wrote:
> Walter Bright wrote:
>
>> kris wrote:
>>
>>> D imports an entire module, into the current namespace (or some
>>> variation upon that). This means that any additions to the original
>>> module have to be aware of the namespace usage of *any* module that
>>> imports the original. Otherwise, a namespace collision will occur and
>>> the combination will fail to compile. M3 import explicitly from each
>>> module instead ~ you can't have such a collision. The value of that
>>> is just as solid today as it was in 1989.
>>>
>>> One might argue that with D, one should create new modules instead of
>>> extending existing ones? That's a fair point until you consider that
>>> the module namespace is limited to one file, and the 'friend' aspect
>>> is limited to one module (private attributes being visible within the
>>> one module). Thus, D suffers this problem in a notable manner.
>>>
>>> I forget whether M3 supports importing into a distinct namespace or
>>> not --- the "import x.y.z. as foo;" syntax -- but that can alleviate
>>> related problems, and would help resolve the current D namespace
>>> conflicts that are quite prevalant?
>>
>>
>>
>> import namespaces are second class citizens in D - they are easily
>> overridden by using aliases or fully qualified lookups:
>>
>> import a; // defines foo()
>> import b; // defines foo()
>>
>> foo(); // ambiguous
>> a.foo(); // doesn't matter if there's a b.foo
>> b.foo(); // works
>>
>> alias a.foo foo;
>> foo(); // works
>>
>> As for import x.y.z. as foo;, you can do:
>>
>> alias x.y.z foo;
>> foo.bar();
>>
>> alias x.y abc;
>> abc.x.bar();
>>
>> alias x def;
>> def.y.z.bar();
>>
>> The alias works at any level you choose to make it. Alias can be used
>> to 'import' any name into the current namespace, making it first class.
>>
>> The second class lookup capability is to make it easier to write quick
>> and dirty programs. Aliases or fully qualified names should be used
>> when writing large, complex apps. Think of it like using private - you
>> wouldn't bother with it for small or throwaway programs, but you
>> wouldn't think of not using it for long lived or complex apps.
>
>
>
> Yes, I'm aware of those various workarounds, but none of them address
> the issue. As I'm sure you're aware of, all of these need to be used at
> the import site ... not in the importee code. This is where the issues
> arise.
>
> What I was getting at is this:
>
> -------------
> module importee;
>
> class Foo {}
> -------------
>
> and
>
> -------------
> module importer;
>
> import importee;
>
> class Bar {}
>
> class Bazooka {}
> -------------
>
>
> now, suppose we later change module importee like so:
>
> -------------
> module importee;
>
> class Foo {}
>
> class Bazooka {}
> -------------
>
> Now, module importer will not compile. It needs to be re-engineered
> regardless, since no amount of aliasing of the /importee module/ will
> work. This is where a bit of foresight should come into play regarding
> import namespaces and so on (within the D language). There are a number
> of solutions available. It is precicely this kind of re-engineering that
> should be rendered completely unecessary.
>
> The second aspect is the whole alias notion is just too weak to handle
> large-scale development. In other languages, the syntax "import x.y.z as
> foo;" actually does create a unique namespace, achieving two things:
>
> a) there's no other way to refer to x.y.z content other than through the
> "foo." prefix. This eliminates the potential for conflicting names
> across multiple modules, regardless of long-term maintenance in any of
> them. Relying on the D "alias" mechanism for such needs is prone to
> abject failure.
>
> b) alias simply provides an /additional/ means of referring to some
> element. All of the original names are still there, from the entirety of
> the imported module. The potential for name collisions, such as two
> classes called 'Bazooka' is painfully obvious.
>
> The whole concept of long-term and/or large-scale development using D as
> a tool is marred by such problems -- it's not very hard to fix either --
> perhaps as simple as the "import x.y.z as foo;" syntax, which is quite
> quite different from the concept of alias. I sincerely hope you'll agree
> on that distinction?
>
>
>
More information about the Digitalmars-d
mailing list