Jump to page: 1 2 3
Thread overview
Import conflict resoultion
Jul 13, 2006
Regan Heath
Jul 13, 2006
Jeremy
Jul 13, 2006
Carlos Santander
Jul 13, 2006
Dave
Jul 13, 2006
kris
Jul 13, 2006
Dave
Jul 13, 2006
Andrei Khropov
Jul 13, 2006
Bruno Medeiros
Jul 13, 2006
Don Clugston
Jul 13, 2006
Dave
Jul 13, 2006
Jeremy
Jul 13, 2006
Dave
Jul 13, 2006
Lucas Goss
Jul 13, 2006
Dave
Jul 13, 2006
Regan Heath
Jul 13, 2006
Jeremy
Jul 13, 2006
kris
Jul 14, 2006
kellywilson
Jul 14, 2006
Georg Wrede
Jul 14, 2006
Regan Heath
Jul 14, 2006
Bruno Medeiros
Jul 15, 2006
Bruno Medeiros
Jul 15, 2006
Regan Heath
Jul 15, 2006
Bruno Medeiros
Jul 16, 2006
Regan Heath
Jul 15, 2006
Tyro
Jul 15, 2006
Bruno Medeiros
July 13, 2006
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.
July 13, 2006
In article <optcludog823k2f5@nrage>, Regan Heath says...
>
>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.

This sounds like a very good summary -- I also like the #4 option :) So #4 + private by default? Sounds good to me!

option[4].vote++;

- jeremy


July 13, 2006
Regan Heath wrote:

[lots of great stuff snipped for brevity]

>   import std.string std.string;

(forces FQN with the original module name)

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

I agree with all of your conclusions, with the caveat for compiler writers that the current alias functionality cannot be used internally to implement this given the above two requirements.

You can't:

alias foo foo;

and:

alias foo myfoo;

doesn't force myfoo to be used over 'foo'.

But I think it is all-around the best solution for the same rational given.

Given your rational and proposal, the _need_ for "specific symbol import" functionality will probably disappear too, keeping the language that much simpler to implement and less to learn and remember in order to maintain code.

import a.popular.db.lib dblib;
alias dblib.open dbopen;
alias dblib.close dbclose;

would be used instead of something like:

import a.popular.db.lib dblib
{
open dbopen;
close dbclose;
}

Not much difference in lines of code or effort to write or scan, the one advantage being that it would tend to keep aliased symbols close to the import (that's still a big advantage though, IMHO).
July 13, 2006
Suspect we've already flogged this to death a number of times, but selective-imports don't appear to give you much functional power above and beyond the prefix-import. Thus it would be entirely optional, IMO. I know Dave has noted this in a prior post, as have others.

Dave wrote:
> Given your rational and proposal, the _need_ for "specific symbol import" functionality will probably disappear too, keeping the language that much simpler to implement and less to learn and remember in order to maintain code.
> 
> import a.popular.db.lib dblib;
> alias dblib.open dbopen;
> alias dblib.close dbclose;
> 
> would be used instead of something like:
> 
> import a.popular.db.lib dblib
> {
> open dbopen;
> close dbclose;
> }
> 
> Not much difference in lines of code or effort to write or scan, the one advantage being that it would tend to keep aliased symbols close to the import (that's still a big advantage though, IMHO).

egad! :)

Would perhaps be simpler to avoid that, and just do this instead:

import a.popular.db.lib db;

db.open ();
db.close ();

As well as being concise and safe, it also clearly indicates just which instance of open/close is being invoked. Those who don't need safe imports can still happily use the existing variety:

import a.popular.lib;

open();
close();
July 13, 2006
In article <e94d1g$9o3$1@digitaldaemon.com>, kris says...
>
>Suspect we've already flogged this to death a number of times, but selective-imports don't appear to give you much functional power above and beyond the prefix-import. Thus it would be entirely optional, IMO. I know Dave has noted this in a prior post, as have others.
>
>Dave wrote:
>> Given your rational and proposal, the _need_ for "specific symbol import" functionality will probably disappear too, keeping the language that much simpler to implement and less to learn and remember in order to maintain code.
>> 
>> import a.popular.db.lib dblib;
>> alias dblib.open dbopen;
>> alias dblib.close dbclose;
>> 
>> would be used instead of something like:
>> 
>> import a.popular.db.lib dblib
>> {
>> open dbopen;
>> close dbclose;
>> }
>> 
>> Not much difference in lines of code or effort to write or scan, the one advantage being that it would tend to keep aliased symbols close to the import (that's still a big advantage though, IMHO).
>
>egad! :)
>
>Would perhaps be simpler to avoid that, and just do this instead:
>
>import a.popular.db.lib db;
>
>db.open ();
>db.close ();
>

You're right - I was getting carried away with matching the C# 'using alias = specific_symbol;' functionality because I like it. But, I haven't seen it used by others that much for specific symbols probably for the same reasons your examples just pointed out. I'd be very happy just to get the prefix-import change pretty much like Regan just described.


July 13, 2006
Regan Heath wrote:

<skipped>

Good survey, thanks.

My vote is for #3 as well as #4 to be available (exact syntax may vary).

("import std.string std.string" is disgusting :-) )

-- 
AKhropov
July 13, 2006
Jeremy escribió:
> 
> This sounds like a very good summary -- I also like the #4 option :) So #4 +
> private by default? Sounds good to me!
> 
> option[4].vote++;
> 
> - jeremy
> 
> 

Same here.
I'd also like #5, and I can live without #3.

-- 
Carlos Santander Bernal
July 13, 2006
Regan Heath wrote:
> 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".


Thanks, Regan. Indeed this is an attempt at conflict resolution in both meanings. Well done.

Seems to me that one of Walter's key non-negotiables is to ensure that:
------------
import std.stdio;

void main()
{
   writefln("Hello, world!");
}
------------
still works. Hopefully all of us can see the importance of that.

Personally, I don't have a strong objection to #3, if it was combined with default private imports, we wouldn't have to type "private static import" all the time, which would IMHO be unacceptable.

However, unlike Kris, I don't have any experience with working with really large projects in D (or any language at all, actually) -- so I'll trust Kris on the need for #4.

#4 would definitely need different syntax, with a clearer visual distinction from a traditional import. Whether it be "import alias std.string str;" or "import std.string as str;" or "import std.string = str;" -- I don't have a strong preference. I don't think there would be any need for it to prevent FQN access.

But really, I'll be happy just as long as we're not left with only #1 and #2. I'm delighted that this fundamental issue is finally getting attention; I'm disappointed at how heated the discussion became.

Thanks again, Regan.
July 13, 2006
Don Clugston wrote:
> Regan Heath wrote:
>> 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".
> 
> 
> Thanks, Regan. Indeed this is an attempt at conflict resolution in both meanings. Well done.
> 
> Seems to me that one of Walter's key non-negotiables is to ensure that:
> ------------
> import std.stdio;
> 
> void main()
> {
>    writefln("Hello, world!");
> }
> ------------
> still works. Hopefully all of us can see the importance of that.
> 
> Personally, I don't have a strong objection to #3, if it was combined with default private imports, we wouldn't have to type "private static import" all the time, which would IMHO be unacceptable.
> 
> However, unlike Kris, I don't have any experience with working with really large projects in D (or any language at all, actually) -- so I'll trust Kris on the need for #4.
> 
> #4 would definitely need different syntax, with a clearer visual distinction from a traditional import. Whether it be "import alias std.string str;" or "import std.string as str;" or "import std.string = str;" -- I don't have a strong preference. I don't think there would be any need for it to prevent FQN access.
>

import std.string as string; // Ok, but new keyword
import std.string : string; // Ok
import std.string string; // Ok: alias-like syntax but not very distinct
import std.string = string; // wrong, = is right-assoc.
import string = std.string; // Ok: concise, distinct, consistent and logically accurate.

I personally like the last because it's the most visually distinctive (makes it hard to miss the alias) and it represents exactly what is going on, but whatever.

I agree there would be no need to prevent FQN access. So there would be no need to allow 'import std.string = std.string;' to force the FQN to use the original name.

Ergo, the current implementation of alias along with the Walter's 'static import' could be used to implement this type of syntax (internal to the compiler) I believe.

> But really, I'll be happy just as long as we're not left with only #1 and #2. I'm delighted that this fundamental issue is finally getting attention; I'm disappointed at how heated the discussion became.
> 
> Thanks again, Regan.
July 13, 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!" ;)
> ...

Nice! Wiki'd!
http://www.prowiki.org/wiki4d/wiki.cgi?ImportConflictResolution

And linked from:
http://www.prowiki.org/wiki4d/wiki.cgi?ImportIssues

I added a section for supported solutions so you can put your name by the number you support (makes me feel like I'm signing a declaration of... independence or something, :) ).

Lucas
« First   ‹ Prev
1 2 3