import concerns (was Re: Historical language survey)

Sean Kelly sean at f4.ca
Fri Jul 7 16:02:40 PDT 2006


kris wrote:
> 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.

You meant modules wumpus and bar :-)

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

This would be the alternate interpretation of the "issue of whether the 
contents of x.y.z are visible without the 'foo' qualifier" in my last 
post.  Personally, I think either interpretation would work as I believe 
collisions only occur when a lookup is being processed, not simply 
because the symbols happen to exist in the various modules, but your 
method would help the user avoid accidental non-qualified use of 
imported symbols.

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

I like this idea irrespective of the other issues being discussed.  For 
example, one irritating issue for implementing Posix headers is that 
they are all inter-dependent, and each header is often required to 
expose particular symbols from other headers.  The only way to do this 
now in D is to publicly import one module entirely into the other 
module, and finer-grained control would be far nicer.  Unfortunately, 
alias can't be used to resolve this issue:

     module A;

     alias foo bar;

----------

     module B;

     private import A;

     alias A.bar bar;

because it causes multiple definition errors.

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

It's because of what Walter said about import namespaces being 
second-class citizens in D.  Any symbol in the current module 
automatically has priority over a same-named symbol in an import module. 
  If you want to use the import symbol instead you must either fully 
qualify it or alias it locally to put it on equal footing with the other 
local symbols.


Sean



More information about the Digitalmars-d mailing list