Import conflict resoultion

Georg Wrede georg.wrede at nospam.org
Thu Jul 13 22:29:59 PDT 2006


Regan Heath wrote:
> Here is my current understanding of the problems and solutions proposed 
> to  date. Comments are welcome, including "enough already! the horse is 
> dead!"  ;)
> 
> Regan
> 
> 
> Import conflict resolution
> --------------------------
> 
> Assumptions
> -----------
> Imports are private by default (Walter seems to like this now?)
> 
> 
> Terminology
> -----------
> FQN = Fully Qualified Name
> 
> 
> Problems
> --------
> A:
> Importing 2 modules with the same symbol causes an immediate collision eg.
> import std.string;
> import std.regexp;
> 
> ..find(.. //error std.string.find or std.regexp.find
> 
> B:
> Changes to a module at a later date may cause a collision at a later date.
> import a;
> import b;
> 
> ..foo(.. //calling a.foo.
> 
> At later date symbol 'foo' is added to b and now the collision occurs.
> 
> 
> Current behaviour
> -----------------
> "How imports work is that first a name is searched for in the current  
> namespace. If it is not found, then it is looked for in the import 
> list.  If it is
> found uniquely among the imports, then that is used. If it is in more 
> than  one import, an error occurs"
>  - Walter
> 
> "Import does not import names into the current namespace. It imports 
> them  into a secondary namespace, that is looked in *only* if the name 
> isn't
> found in the current namespace. Alias can then cherry-pick specific  
> symbols out of that secondary namespace and put them in the current  
> namespace,
> possibly renaming them along the way."
>  - Walter
> 
> 
> Current solutions
> -----------------
> 1:
> import std.string;
> import std.regexp;
> alias std.string.find find;
> 
> ..find(.. //no error std.string.find is called
> 
> 2:
> import std.string;
> import std.regexp;
> 
> ..std.string.find(.. //no error FQN is used
> 
> 
> Opinions/pros/cons on the current solutions
> -------------------------------------------
> 
> 1:
>  - PRO,Solves the import conflict for the intended symbol.
>  - CON,Does NOT solve future symbol conflicts.
>  - CON,The alias is 'physically' seperate from the import.
> 
> 2:
>  - PRO,Solves the import conflict for the intended symbol.
>  - CON,Does NOT solve future symbol conflicts.
>  - CON,Causes more verbose code.
> 
> Neither of these current solutions solves B.
> 
> 
> Proposed solutions
> ------------------
> 3:
> Prevent import into the "secondary namespace", only allow FQN access. 
> (AKA  "static import")
> static import std.string; //exact syntax may vary
> static import std.regexp; //exact syntax may vary
> 
> ..find(.. //error
> ..std.string.find(.. //ok
> ..std.regexp.find(.. //ok
> 
> "All 'static import' does is eliminate the "if the name is not found in  
> the current module, look in the imports" step. This has the effect of
> requiring the use of FQN's when referencing imports."
>  - Walter
> 
> 4:
> Import into a custom namespace, eg.
> import std.string str; //exact syntax may vary
> import std.regexp;
> 
> ..str.find(.. //calls std.string.find
> ..find(.. //calls std.regexp.find
> 
> This method should also prevent import into the "secondary namespace".
> 
> 5:
> Allow selective import of the exact symbol which is required.
> import std.string.find; //exact syntax may vary
> 
> ..find(.. //calls std.string.find
> 
> No symbols from std.string would be present in the "secondary namespace".
> 
> 
> Opinions/pros/cons on the various solutions
> -------------------------------------------
> 
> 3:
>  - PRO,Solves the import conflict for the intended symbol.
>  - PRO,Solves future symbol conflicts in the same module(s).
>  - CON,Causes more verbose code, using FQN all the time.
> 
> 4:
>  - PRO,Solves the import conflict for the intended symbol.
>  - PRO,Solves future symbol conflicts in the same module(s).
> 
> 5:
>  - PRO,Solves the import conflict for the intended symbol.
>  - CON,Does NOT solve future symbol conflicts.
> 
> 
> Conclusions, extra thoughts
> ---------------------------
> 
> The ideal solution IMO is #4, it solves both A and B in a simple, easy 
> and  elegant(IMO) fashion something that cannot
> be said about the existing solutions #1 and #2.
> 
> To the people who want FQN all the time.. You may view the proposed  
> solutions #3 and #4 as identical (in value to you).
> The deciding factor to my mind is that other people do not want to use 
> FQN  all the time therefore #4 makes the most
> people happy. The interesting thing, is that FQN can be achieved with  
> soltion #4, note that:
>   import std.string std.string;
> 
> would be FQN access, without! any further special syntax (like 
> "static"),  to me this makes #4 better than #3
> even if you want to use FQN.
> 
> Yes, it requires more typing but I don't think you can complain about  
> having to type the module name once more
> when you plan to type it 20+ more times in the course of the file, can you?
> 
> FQN access is curently always present, but not required. However, with  
> solution #4 FQN access to the symbol is no longer
> ever required. It's presence results in code which can call the same  
> function in more than one way. This allows the code to
> be inconsistent for no gain (that I can imagine) therefore i think that  
> solution #4 should prevent FQN access to symbols.

Out of these, I'd want #4 and #5 combined.

Except that I don't understand the following:

 > 5:
 > Allow selective import of the exact symbol which is required.
 > import std.string.find; //exact syntax may vary
 >
 > ..find(.. //calls std.string.find
 >
 > No symbols from std.string would be present in the "secondary namespace".
 >
 >
 > Opinions/pros/cons on the various solutions
 > -------------------------------------------
 >
 > 5:
 >  - PRO,Solves the import conflict for the intended symbol.
 >  - CON,Does NOT solve future symbol conflicts.

It was stated that "No symbols from std.string would be present in the 
"secondary namespace". Therefore I don't understand the CON argument 
"Does NOT solve future symbol conflicts".

-----------------

Anyhow, I officially want to

1: be able to import a module into an arbitrary namespace

     import foo.bar.baz.gawk.gasp.stuff as crap;

or even

     import foo.bar.baz.gawk.gasp.stuff as foo.bar.baz.gawk.gasp.stuff;
     // if I so care to choose. ;-/

2: be able to import arbitrary module-top-level-identifiers, without 
importing the rest of the module

     import da.njet.ruskiij.svesda.myfunc as f;

3: retain compatibility with legacy D code

     import foo.bar;  // All of both go to the "secondary name space",
     import baz.baw;  // as hitherto. (With risk of conflict. :-)  )

1, 2 and 3 should all be usable in the same file!

     import foo.fii.faa;
     import doo.dii.daa.aFunc as df;
     import boo.bii.baa as b;

----

So, Regan, you may count my contribution as you like, here I've just 
presented what I honestly want, without careful regard [or precise 
understanding] of the Numbered Categories.


################################

And even here I have to beg, crawl, kiss A, threat, --- or just ask Walter:

    Pretty please, please do include the word "as" in the import 
statement, please!

I know that it's not needed (i.e., a space would do), I know there are 
numerous other alternatives ":", "=", you-name-it.

But for the educational motivations you _yourself_ brought up a couple 
of messages ago, and for corporate code maintenance, or newbie fluency 
issues (which nobody has yet brought up), please retain the word "as" here.

It really doesn't waste /that/ much of ink.





More information about the Digitalmars-d mailing list