www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Nested public imports - bug or feature?

reply "Dicebot" <public dicebot.lv> writes:
Right now this works:

``D
struct Std
{
   public import std.stdio;
}

void main()
{
   Std.writeln("Nice!");
}
```

I want to use it as an import hygiene idiom but not entirely sure 
if this behavior can be relied upon (or it is just a side effect 
of imports being implemented as aliases currently).
Aug 13 2015
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 13 August 2015 at 13:12:44 UTC, Dicebot wrote:
 Right now this works:

 ``D
 struct Std
 {
   public import std.stdio;
 }

 void main()
 {
   Std.writeln("Nice!");
 }
 ```

 I want to use it as an import hygiene idiom but not entirely 
 sure if this behavior can be relied upon (or it is just a side 
 effect of imports being implemented as aliases currently).
Well, that's pretty much why splitting up a module and putting public imports in its package.d file doesn't break any of the cases where someone types out the full import path when referring to something from that module/package. But I doubt that anyone considered that that would have this effect when you have a scoped import. In fact, to be honest, it never occurred to me that it would be legal to have a scoped, public import. I think that you just hit a weird result of how allowing imports to be put everywhere ended up working. I confess that I don't particularly like that this is legal (and I think that public imports tend to get a bit hinky because of the fact that they create aliases), and I'm not quite sure how you could use it form "import hygiene," but I also don't see how this could work any other way if scoped, public imports are allowed. - Jonathan M Davis
Aug 13 2015
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 03:42 PM, Jonathan M Davis wrote:
 On Thursday, 13 August 2015 at 13:12:44 UTC, Dicebot wrote:
 Right now this works:

 ``D
 struct Std
 {
   public import std.stdio;
 }

 void main()
 {
   Std.writeln("Nice!");
 }
 ```

 I want to use it as an import hygiene idiom but not entirely sure if
 this behavior can be relied upon (or it is just a side effect of
 imports being implemented as aliases currently).
Well, that's pretty much why splitting up a module and putting public imports in its package.d file doesn't break any of the cases where someone types out the full import path when referring to something from that module/package. But I doubt that anyone considered that that would have this effect when you have a scoped import. In fact, to be honest, it never occurred to me that it would be legal to have a scoped, public import. I think that you just hit a weird result of how allowing imports to be put everywhere ended up working. I confess that I don't particularly like that this is legal (and I think that public imports tend to get a bit hinky because of the fact that they create aliases), and I'm not quite sure how you could use it form "import hygiene,"
It has nothing to do with the import being public. This works: --- struct Std{ import std.stdio; } void main(){ Std.writeln("Nice!"); } --- (It also works if main and Std are defined in different modules.)
 but I also don't see how this could work any other way
 if scoped, public imports are allowed.
...
Easy. Just treat aggregate scopes and module scopes differently. (They are treated differently even now: all imports are 'public' in aggregate scopes, but not at module scope.) I think this shouldn't be done though. In any case, I guess we agree that this idiom should work for public imports, but not for non-public ones (so the current behaviour with non-public imports is accepts-invalid, but Dicebot's code should be fine)?
Aug 13 2015
next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 13-Aug-2015 16:56, Timon Gehr wrote:
[snip]
 It has nothing to do with the import being public. This works:

 ---
 struct Std{
      import std.stdio;
 }
 void main(){
      Std.writeln("Nice!");
 }
 ---

 (It also works if main and Std are defined in different modules.)

 but I also don't see how this could work any other way
 if scoped, public imports are allowed.
 ...
Easy. Just treat aggregate scopes and module scopes differently. (They are treated differently even now: all imports are 'public' in aggregate scopes, but not at module scope.) I think this shouldn't be done though. In any case, I guess we agree that this idiom should work for public imports, but not for non-public ones (so the current behaviour with non-public imports is accepts-invalid, but Dicebot's code should be fine)?
Agreed, public import case looks legitimate. -- Dmitry Olshansky
Aug 13 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 13:56:24 UTC, Timon Gehr wrote:
 It has nothing to do with the import being public. This works:

 ---
 struct Std{
     import std.stdio;
 }
 void main(){
     Std.writeln("Nice!");
 }
 ---

 (It also works if main and Std are defined in different 
 modules.)
Ah, I thought alias injection is only done for public ones. Same question applies though :)
 In any case, I guess we agree that this idiom should work for 
 public imports, but not for non-public ones (so the current 
 behaviour with non-public imports is accepts-invalid, but 
 Dicebot's code should be fine)?
I am very curious to learn "official" answer :)
Aug 13 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 05:34 PM, Dicebot wrote:
 In any case, I guess we agree that this idiom should work for public
 imports, but not for non-public ones (so the current behaviour with
 non-public imports is accepts-invalid, but Dicebot's code should be
 fine)?
I am very curious to learn "official" answer :)
If there is only one sane/consistent/turtles/etc choice for the behaviour of some feature, typically, assuming that /eventually/ this choice will be made works.
Aug 13 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 13:42:42 UTC, Jonathan M Davis 
wrote:
 I confess that I don't particularly like that this is legal 
 (and I think that public imports tend to get a bit hinky 
 because of the fact that they create aliases), and I'm not 
 quite sure how you could use it form "import hygiene," but I 
 also don't see how this could work any other way if scoped, 
 public imports are allowed.
It won't work if you define importing as adding module to internal scope symbol lookup table, without actually adding imported symbols to scope.
Aug 13 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 05:35 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 13:42:42 UTC, Jonathan M Davis wrote:
 I confess that I don't particularly like that this is legal (and I
 think that public imports tend to get a bit hinky because of the fact
 that they create aliases), and I'm not quite sure how you could use it
 form "import hygiene," but I also don't see how this could work any
 other way if scoped, public imports are allowed.
It won't work if you define importing as adding module to internal scope symbol lookup table, without actually adding imported symbols to scope.
It's about _public_ imports, which are special. (Also, you don't need to "actually" add imported symbols to any scope. The "redirect" method also works for '.' access.)
Aug 13 2015
prev sibling next sibling parent reply "rsw0x" <anonymous anonymous.com> writes:
On Thursday, 13 August 2015 at 13:12:44 UTC, Dicebot wrote:
 Right now this works:

 ``D
 struct Std
 {
   public import std.stdio;
 }

 void main()
 {
   Std.writeln("Nice!");
 }
 ```

 I want to use it as an import hygiene idiom but not entirely 
 sure if this behavior can be relied upon (or it is just a side 
 effect of imports being implemented as aliases currently).
And we're back to namespaces : )
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 13:44:50 UTC, rsw0x wrote:
 And we're back to namespaces : )
Not really. This is namespace: ----- module a; struct Something { static void foo() {} } module b; import a; void main() { Something.foo(); } ----- This is import hygiene: ----- module a; void foo() { } module b; struct Something { public import a; } void main() { Something.foo(); } ----- Without that you risk breaking the code each time you add new symbol to a library - D module system is completely broken in that regard.
Aug 13 2015
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 05:29 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 13:44:50 UTC, rsw0x wrote:
 And we're back to namespaces : )
Not really. This is namespace: ----- module a; struct Something { static void foo() {} } module b; import a; void main() { Something.foo(); } ----- This is import hygiene: ----- module a; void foo() { } module b; struct Something { public import a; } void main() { Something.foo(); } ----- Without that you risk breaking the code each time you add new symbol to a library -
You know about static imports, right?
 D module system is completely broken in that regard.
What's the alternative?
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 15:40:12 UTC, Timon Gehr wrote:
 You know about static imports, right?
Yes, as well as about renamed and selective ones ;) Problem with static imports is that they are all-or-nothing. And in our projects it is common to have module names with 5 nested packages or even more. Typing all of it is impractical - simple prefix gives enough protection from random clashes.
 D module system is completely broken in that regard.
What's the alternative?
When doing my old "Rust vs D" comparison I have been mentioning their import semantics as a big win. When you do import like this: use phrases::english::greetings; You must always also qualify symbol name with module name like this: println!("Hello in English: {}", greetings::hello()); And this won't compile: println!("Hello in English: {}", hello()); It has similar benefits as the idiom proposed in this topic - greatly reduced risk of accidental clashes.
Aug 13 2015
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 05:49 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 15:40:12 UTC, Timon Gehr wrote:
 You know about static imports, right?
Yes, as well as about renamed and selective ones ;) Problem with static imports is that they are all-or-nothing.
(Which is an arbitrary restriction most likely motivated by implementation difficulties.)
 And in our
 projects it is common to have module names with 5 nested packages or
 even more. Typing all of it is impractical - simple prefix gives enough
 protection from random clashes.

 D module system is completely broken in that regard.
What's the alternative?
When doing my old "Rust vs D" comparison I have been mentioning their import semantics as a big win. When you do import like this: use phrases::english::greetings; You must always also qualify symbol name with module name like this: println!("Hello in English: {}", greetings::hello()); And this won't compile: println!("Hello in English: {}", hello()); It has similar benefits as the idiom proposed in this topic - greatly reduced risk of accidental clashes.
static import greetings=phrases.english.greetings; ?
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 15:59:46 UTC, Timon Gehr wrote:
 On 08/13/2015 05:49 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 15:40:12 UTC, Timon Gehr wrote:
 You know about static imports, right?
Yes, as well as about renamed and selective ones ;) Problem with static imports is that they are all-or-nothing.
(Which is an arbitrary restriction most likely motivated by implementation difficulties.)
Well I prefer to work with tools I have right now and not wait for something sane to be implemented.
 static import greetings=phrases.english.greetings;

 ?
http://forum.dlang.org/post/szaaakmavraxatkrfpnx forum.dlang.org
Aug 13 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 06:19 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 15:59:46 UTC, Timon Gehr wrote:
 On 08/13/2015 05:49 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 15:40:12 UTC, Timon Gehr wrote:
 You know about static imports, right?
Yes, as well as about renamed and selective ones ;) Problem with static imports is that they are all-or-nothing.
(Which is an arbitrary restriction most likely motivated by implementation difficulties.)
Well I prefer to work with tools I have right now and not wait for something sane to be implemented. ...
(It's about communicating clearly what the problem actually is. static imports are not inherently all-or-nothing.)
 When doing my old "Rust vs D" comparison I have been mentioning their
 import semantics as a big win. When you do import like this:

 use phrases::english::greetings;

 You must always also qualify symbol name with module name like this:

 println!("Hello in English: {}", greetings::hello());

 And this won't compile:

 println!("Hello in English: {}", hello());

 It has similar benefits as the idiom proposed in this topic - greatly
 reduced risk of accidental clashes.
static import greetings=phrases.english.greetings; ?
http://forum.dlang.org/post/szaaakmavraxatkrfpnx forum.dlang.org
How is this relevant? Does Rust support it?
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 16:24:56 UTC, Timon Gehr wrote:
 static import greetings=phrases.english.greetings;

 ?
http://forum.dlang.org/post/szaaakmavraxatkrfpnx forum.dlang.org
How is this relevant? Does Rust support it?
Relevant as explanation why I don't consider aliased imports a solution. Rust does exactly that and I feel that "bottom-qualification" is inferior approach to "top-qualification" in general for deeply nested package hierarchies. Of course, both are much more hygienic than semantics D uses by default - yet if I am forced to resort to idioms, I want to get most out of it :)
Aug 13 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 06:36 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 16:24:56 UTC, Timon Gehr wrote:
 static import greetings=phrases.english.greetings;

 ?
http://forum.dlang.org/post/szaaakmavraxatkrfpnx forum.dlang.org
How is this relevant? Does Rust support it?
Relevant as explanation why I don't consider aliased imports a solution. Rust does exactly that and I feel that "bottom-qualification" is inferior approach to "top-qualification" in general for deeply nested package hierarchies. Of course, both are much more hygienic than semantics D uses by default
I am unable to understand your concerns precisely, because you are making up words without giving definitions or examples. https://www.google.ch/search?q=module+system+bottom-qualification https://www.google.ch/search?q=module+system+top-qualification https://www.google.ch/search?q=define+hygienic+module+system
 - yet if I am forced to resort to idioms, I want to get most out of it :)
This was the example given in that post:
 import mypkg = mypkg.mysubpkg.mod1;
 import mypkg = mypkg.mysubpkg.mod2; // error, can't redefine aliased import!

 struct mypkg
 {
     import mypkg.mysubpkg.mod1;
     import mypkg.mysubpkg.mod2; // fine
 }
FWIW: --- use mypkg::mysubpkg::mod1 as myuse; use mypkg::mysubpkg::mod2 as myuse; --- error: a module named `myuse` has already been imported in this module [E0252] use mypkg::mysubpkg::mod2 as myuse; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You have to resort to the following idiom: mod myuse{ pub use mypkg::mysubpkg::mod1::*; pub use mypkg::mysubpkg::mod2::*; } Now, note: if there is any identifier `foo' which is exported by both `mod1' and `mod2', then the Rust compiler will error out eagerly here, even if `myuse::foo' never occurs in the code. How is this superior? AFAICS, the only other major semantic difference which would make Rust's system vastly superior is given by the situation that DMD comically thinks private symbols have a reason to cause conflicts in other modules. Was this your "hygiene" point?
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
Ok, let's stop for a minute and make sure we are on the same 
thread here. Because you seem to argue something I have never 
said or at least intended to say.

So, my basic statements:

1. I don't like default D import semantics but I am not proposing 
to change it
2. I like Rust default import semantics (requiring module name) 
more than default D one. It is possible to emulate it by turning 
every single import into aliased import.
3. Idiom proposed in the first post is based on similar reasoning 
as Rust behavior but is different in functionality (one I find 
even more practical personally).
4. Both feel more practical to me than default D behavior and 
both require custom idioms/conventions in D

Does that make sense?
Aug 14 2015
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/14/2015 08:57 PM, Dicebot wrote:
 Ok, let's stop for a minute and make sure we are on the same thread
 here. Because you seem to argue something I have never said or at least
 intended to say.
 ...
OK. This is my view: The sub-thread was started with the claim that the module system is "completely broken" in a particular way. You gave Rust's system as an alternative, but it is (basically) the same thing with slightly different syntax.
 So, my basic statements:

 1. I don't like default D import semantics but I am not proposing to
 change it
 2. I like Rust default import semantics (requiring module name) more
 than default D one. It is possible to emulate it by turning every single
 import into aliased import.
 3. Idiom proposed in the first post is based on similar reasoning as
 Rust behavior but is different in functionality (one I find even more
 practical personally).
 4. Both feel more practical to me than default D behavior and both
 require custom idioms/conventions in D

 Does that make sense?
Not really. It is up to the programmer which of the idioms to use by default, and all options exist in both languages. It's not that important, I guess.
Aug 14 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Friday, 14 August 2015 at 20:12:43 UTC, Timon Gehr wrote:
 On 08/14/2015 08:57 PM, Dicebot wrote:
 Ok, let's stop for a minute and make sure we are on the same 
 thread
 here. Because you seem to argue something I have never said or 
 at least
 intended to say.
 ...
OK. This is my view: The sub-thread was started with the claim that the module system is "completely broken" in a particular way. You gave Rust's system as an alternative, but it is (basically) the same thing with slightly different syntax.
I called it broken because it makes impossible to add new symbols to the library without possibly breaking user code. Same scenario in Rust is much less likely - comparing default import semantics, of course. And idioms don't matter because only very few use them, thus I only consider default import behaviour when making such statement. Still disagree?
 Does that make sense?
Not really. It is up to the programmer which of the idioms to use by default, and all options exist in both languages. It's not that important, I guess.
Won't try to convince anyone about good style and stuff. All I need is some confirmation that presented nested import semantics will stay :( Will try poking Walter personally.
Aug 15 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/15/2015 06:15 PM, Dicebot wrote:
 On Friday, 14 August 2015 at 20:12:43 UTC, Timon Gehr wrote:
 On 08/14/2015 08:57 PM, Dicebot wrote:
 Ok, let's stop for a minute and make sure we are on the same thread
 here. Because you seem to argue something I have never said or at least
 intended to say.
 ...
OK. This is my view: The sub-thread was started with the claim that the module system is "completely broken" in a particular way. You gave Rust's system as an alternative, but it is (basically) the same thing with slightly different syntax.
I called it broken because it makes impossible to add new symbols to the library without possibly breaking user code. Same scenario in Rust is much less likely - comparing default import semantics, of course. And idioms don't matter because only very few use them, thus I only consider default import behaviour when making such statement. Still disagree? ...
Sure, but I think the disagreement is on what it /means/ for a module system to be broken, hence it is not actually important. Thanks!
 Does that make sense?
Not really. It is up to the programmer which of the idioms to use by default, and all options exist in both languages. It's not that important, I guess.
Won't try to convince anyone about good style and stuff. All I need is some confirmation that presented nested import semantics will stay :( Will try poking Walter personally.
Ok. Still "yes" is the only answer that makes any sense, and breaking legitimate D code is not among Walter's priorities. :-)
Aug 15 2015
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 13 August 2015 at 15:49:10 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 15:40:12 UTC, Timon Gehr wrote:
 You know about static imports, right?
Yes, as well as about renamed and selective ones ;) Problem with static imports is that they are all-or-nothing. And in our projects it is common to have module names with 5 nested packages or even more. Typing all of it is impractical - simple prefix gives enough protection from random clashes.
 D module system is completely broken in that regard.
What's the alternative?
When doing my old "Rust vs D" comparison I have been mentioning their import semantics as a big win. When you do import like this: use phrases::english::greetings; You must always also qualify symbol name with module name like this: println!("Hello in English: {}", greetings::hello()); And this won't compile: println!("Hello in English: {}", hello()); It has similar benefits as the idiom proposed in this topic - greatly reduced risk of accidental clashes.
You can get that behavior with static imports in D, but having to use the whole import path while referencing symbols gets ugly fast. There's a reason that using directives get used heavily in C++, though at least there, if you're behaving yourself and not using using directives in .h files, that doesn't affect #includes, unlike with D's import (though having to fully qualify everything in header files is always annoying). But you still end up with potential breakage in .cpp files due to new symbols being introduced which clash. I honestly don't see a good solution to the problem, because requiring that you fully qualify symbols is incredibly annoying and hideous, but if you don't, then adding symbols to a module is always going to break code. As far as I can tell, your module system is stuck with one poison or the other. Maybe something similar to using directives that didn't leak outside of the module would be a reasonable compromise, but then many folks would just have a using directive for every import in order to avoid having to fully qualify symbols. So, I really don't see a good solution, and while the potential breakage caused by D's solution is annoying, I'd much rather have that then be forced to use fully qualified names. - Jonathan M Davis
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 16:19:29 UTC, Jonathan M Davis 
wrote:
 You can get that behavior with static imports in D, but having 
 to use the whole import path while referencing symbols gets 
 ugly fast.
Check example again, you are only required to use the plain module name, not fully qualified one. With D syntax: import std.stdio; writeln(); // not good stdio.writeln(); // good std.stdio.writeln(); // also good, but not required
Aug 13 2015
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/13/2015 06:22 PM, Dicebot wrote:
 On Thursday, 13 August 2015 at 16:19:29 UTC, Jonathan M Davis wrote:
 You can get that behavior with static imports in D, but having to use
 the whole import path while referencing symbols gets ugly fast.
Check example again, you are only required to use the plain module name, not fully qualified one. With D syntax: import std.stdio; writeln(); // not good stdio.writeln(); // good std.stdio.writeln(); // also good, but not required
static import std.stdio; private alias stdio=std.stdio;
Aug 13 2015
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 13 August 2015 at 16:22:04 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 16:19:29 UTC, Jonathan M Davis 
 wrote:
 You can get that behavior with static imports in D, but having 
 to use the whole import path while referencing symbols gets 
 ugly fast.
Check example again, you are only required to use the plain module name, not fully qualified one. With D syntax: import std.stdio; writeln(); // not good stdio.writeln(); // good std.stdio.writeln(); // also good, but not required
Well, that's better than requiring the full import path, but requiring _any_ module name is just plain annoying IMHO. If I were okay with that I wouldn't be doing stuff like using namespace std; in all of my .cpp files - and that's a really common thing to do. - Jonathan M Davis
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 16:37:00 UTC, Jonathan M Davis 
wrote:
 Well, that's better than requiring the full import path, but 
 requiring _any_ module name is just plain annoying IMHO. If I 
 were okay with that I wouldn't be doing stuff like

 using namespace std;

 in all of my .cpp files - and that's a really common thing to 
 do.
Matter of scale. At some point of application size maintenance cost become much higher than development costs - and problems of name clashes become more important than any extra typing annoyance. In my C++ projects such "using" abuse was normally banned.
Aug 13 2015
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 13 August 2015 at 16:40:31 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 16:37:00 UTC, Jonathan M Davis 
 wrote:
 Well, that's better than requiring the full import path, but 
 requiring _any_ module name is just plain annoying IMHO. If I 
 were okay with that I wouldn't be doing stuff like

 using namespace std;

 in all of my .cpp files - and that's a really common thing to 
 do.
Matter of scale. At some point of application size maintenance cost become much higher than development costs - and problems of name clashes become more important than any extra typing annoyance.
Well, if name clashes become that high in a .cpp file, odds are that it's pulling in too much stuff.
 In my C++ projects such "using" abuse was normally banned.
I've never worked on a team that banned them. Every C++ project that I've ever worked on has used them heavily. It's common practice for every namespace that's being used in a .cpp file to having a corresponding using directive. On the rare cases where there's a collision, you then have to be more explicit, but I've never seen it be much of a problem - and definitely nowhere near enough of a problem to consider banning using directives. I'd _hate_ to be writing code that required being that explicit. - Jonathan M Davis
Aug 13 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 17:06:18 UTC, Jonathan M Davis 
wrote:
 Matter of scale. At some point of application size maintenance 
 cost become much higher than development costs - and problems 
 of name clashes become more important than any extra typing 
 annoyance.
Well, if name clashes become that high in a .cpp file, odds are that it's pulling in too much stuff.
My projects have been broken twice by adding new functions to druntime (and one was symbol added to object.di :)). Forgive me if I discard that argument as nonsense. If short names are allowed and project is big enough, clashes are simply inevitable. With D module system even medium size will do.
Aug 13 2015
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 13 August 2015 at 17:09:11 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 17:06:18 UTC, Jonathan M Davis 
 wrote:
 Matter of scale. At some point of application size 
 maintenance cost become much higher than development costs - 
 and problems of name clashes become more important than any 
 extra typing annoyance.
Well, if name clashes become that high in a .cpp file, odds are that it's pulling in too much stuff.
My projects have been broken twice by adding new functions to druntime (and one was symbol added to object.di :)). Forgive me if I discard that argument as nonsense. If short names are allowed and project is big enough, clashes are simply inevitable. With D module system even medium size will do.
Yes. Clashes are going to happen, especially if you're using short names heavily, but in C++, I've rarely had problems with it. D is potentially worse, because we don't have the equivalent separation of header and source files where it's only the source files that risk breakage. But still, I'd _much_ rather just deal with the occasional breakage than have to qualify everything. - Jonathan M Davis
Aug 13 2015
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 13-Aug-2015 20:17, Jonathan M Davis wrote:
 On Thursday, 13 August 2015 at 17:09:11 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 17:06:18 UTC, Jonathan M Davis wrote:
 Matter of scale. At some point of application size maintenance cost
 become much higher than development costs - and problems of name
 clashes become more important than any extra typing annoyance.
Well, if name clashes become that high in a .cpp file, odds are that it's pulling in too much stuff.
My projects have been broken twice by adding new functions to druntime (and one was symbol added to object.di :)). Forgive me if I discard that argument as nonsense. If short names are allowed and project is big enough, clashes are simply inevitable. With D module system even medium size will do.
Yes. Clashes are going to happen, especially if you're using short names heavily, but in C++, I've rarely had problems with it. D is potentially worse,
Because private symbols from imported modules *do* clash with public ones even though not accessible. THAT is the problem and header/source is not the reason of D doing worse here.
 because we don't have the equivalent separation of header and
 source files where it's only the source files that risk breakage. But
 still, I'd _much_ rather just deal with the occasional breakage than
 have to qualify everything.

 - Jonathan M Davis
-- Dmitry Olshansky
Aug 13 2015
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, 13 August 2015 at 17:32:33 UTC, Dmitry Olshansky 
wrote:
 On 13-Aug-2015 20:17, Jonathan M Davis wrote:
 On Thursday, 13 August 2015 at 17:09:11 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 17:06:18 UTC, Jonathan M Davis 
 wrote:
 Matter of scale. At some point of application size 
 maintenance cost
 become much higher than development costs - and problems of 
 name
 clashes become more important than any extra typing 
 annoyance.
Well, if name clashes become that high in a .cpp file, odds are that it's pulling in too much stuff.
My projects have been broken twice by adding new functions to druntime (and one was symbol added to object.di :)). Forgive me if I discard that argument as nonsense. If short names are allowed and project is big enough, clashes are simply inevitable. With D module system even medium size will do.
Yes. Clashes are going to happen, especially if you're using short names heavily, but in C++, I've rarely had problems with it. D is potentially worse,
Because private symbols from imported modules *do* clash with public ones even though not accessible. THAT is the problem and header/source is not the reason of D doing worse here.
Oh. That makes the problem even worse, and it definitely needs to be fixed, but the fact that you're essentially forced to use fully qualified names in C++ for header files means that you're not going to run into name clashes in the public declarations - only in the function bodies in the .cpp file - whereas all of that is out in the open with .d files. So, the header/source separation does reduce the problem in C++, and even if we do fix the private symbol mess in D, D will still have more name clashing problems because it doesn't normally have that separation. But the private symbols affecting the public API is just plain embarrassing and definitely makes the problem _far_ worse. - Jonathan M Davis
Aug 13 2015
parent "Meta" <jared771 gmail.com> writes:
On Thursday, 13 August 2015 at 17:51:06 UTC, Jonathan M Davis 
wrote:
 But the private symbols affecting the public API is just plain 
 embarrassing and definitely makes the problem _far_ worse.

 - Jonathan M Davis
It's worse than embarassing. Every symbol added, public or private, must be considered a breaking change.
Aug 13 2015
prev sibling parent "jmh530" <john.michael.hall gmail.com> writes:
On Thursday, 13 August 2015 at 16:40:31 UTC, Dicebot wrote:
 Matter of scale. At some point of application size maintenance 
 cost become much higher than development costs - and problems 
 of name clashes become more important than any extra typing 
 annoyance.

 In my C++ projects such "using" abuse was normally banned.
I would add that it's not just C++. It is also common in Python to use the full name, albeit typically with an alias, e.g. import numpy as np. One benefit of this approach is that you can easily find every function using numpy in a file. So, while I'm sympathetic with Jonathan's point about requiring the module being a little annoying if you're doing something small, I think you raise a good point about large projects. Nevertheless, others have already pointed out options for allowing the control that you need. If you think that you should be able to re-define imports, then submit an enhancement request. I looked for any suggesting it, but didn't see anything. I did see a few others related to imports that were interesting like allowing something like import std { array, range; }
Aug 13 2015
prev sibling parent reply "Dejan Lekic" <dejan.lekic gmail.com> writes:
On Thursday, 13 August 2015 at 16:22:04 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 16:19:29 UTC, Jonathan M Davis 
 wrote:
 You can get that behavior with static imports in D, but having 
 to use the whole import path while referencing symbols gets 
 ugly fast.
Check example again, you are only required to use the plain module name, not fully qualified one. With D syntax: import std.stdio; writeln(); // not good stdio.writeln(); // good std.stdio.writeln(); // also good, but not required
Thank God, D does it the "not good" way. But I guess that is subjective thing. Some people like it one way, others like it the other way. I humbly belive D's way is good. Compiler should issue a warning when conflicts arrive. This is not Python for Haven's sake!
Aug 14 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/14/2015 05:55 PM, Dejan Lekic wrote:
 On Thursday, 13 August 2015 at 16:22:04 UTC, Dicebot wrote:
 On Thursday, 13 August 2015 at 16:19:29 UTC, Jonathan M Davis wrote:
 You can get that behavior with static imports in D, but having to use
 the whole import path while referencing symbols gets ugly fast.
Check example again, you are only required to use the plain module name, not fully qualified one. With D syntax: import std.stdio; writeln(); // not good stdio.writeln(); // good std.stdio.writeln(); // also good, but not required
Thank God, D does it the "not good" way. But I guess that is subjective thing. Some people like it one way, others like it the other way. ...
Rust supports both. D supports both. I still fail to see how one language can be seen to handle it in a "good" way and the other in a "not good" way, beyond trivial syntactic considerations and compiler bugs. Is it a language-cultural issue?
 I humbly belive D's way is good. Compiler should issue a warning when
 conflicts arrive.
But only then, please. :o)
Aug 14 2015
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Thursday, 13 August 2015 at 15:29:19 UTC, Dicebot wrote:
 struct Something
 {
     public import a;
 }

 void main() { Something.foo(); }
What's wrong with `import Something = a;`? Bugs?
Aug 13 2015
next sibling parent "Meta" <jared771 gmail.com> writes:
On Thursday, 13 August 2015 at 15:53:16 UTC, anonymous wrote:
 On Thursday, 13 August 2015 at 15:29:19 UTC, Dicebot wrote:
 struct Something
 {
     public import a;
 }

 void main() { Something.foo(); }
What's wrong with `import Something = a;`? Bugs?
Even better: feature.
Aug 13 2015
prev sibling parent "Dicebot" <public dicebot.lv> writes:
On Thursday, 13 August 2015 at 15:53:16 UTC, anonymous wrote:
 On Thursday, 13 August 2015 at 15:29:19 UTC, Dicebot wrote:
 struct Something
 {
     public import a;
 }

 void main() { Something.foo(); }
What's wrong with `import Something = a;`? Bugs?
Works only with a single import: import mypkg = mypkg.mysubpkg.mod1; import mypkg = mypkg.mysubpkg.mod2; // error, can't redefine aliased import! struct mypkg { import mypkg.mysubpkg.mod1; import mypkg.mysubpkg.mod2; // fine }
Aug 13 2015
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
As long as imports are not hygienic, this trick is useful. I 

Aug 13 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 8/13/2015 6:12 AM, Dicebot wrote:
 Right now this works:

 ``D
 struct Std
 {
    public import std.stdio;
 }

 void main()
 {
    Std.writeln("Nice!");
 }
 ```

 I want to use it as an import hygiene idiom but not entirely sure if this
 behavior can be relied upon (or it is just a side effect of imports being
 implemented as aliases currently).
It has nothing to do with aliases. Imports work the same way as template mixins do. They share the same implementation code. Since the import is qualified with 'public', I see no reason to change this behavior.
Aug 19 2015
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/20/2015 01:25 AM, Walter Bright wrote:
 I want to use it as an import hygiene idiom but not entirely sure if this
 behavior can be relied upon (or it is just a side effect of imports being
 implemented as aliases currently).
It has nothing to do with aliases. Imports work the same way as template mixins do. They share the same implementation code.
This is exactly the right way to do it. Note that alias this doesn't get this right currently. It can be hijacked by local imports.
Aug 19 2015