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