Re: Scoped Imports for Structs/Classes/Template Constraints

2015-09-01 Thread Enamex via Digitalmars-d-learn

On Tuesday, 1 September 2015 at 15:50:40 UTC, jmh530 wrote:
I'm following some of your post, but not quite all of it 
(particularly the part at the end, and I also think static 
imports can't be selective). Anyway, I was thinking about 
something like below as one possible alternative


struct T
{
import local : S;
void foo(S s)
{
import std.stdio : writeln;
writeln(s.a);
}
}


Bad idea to wrap it in a struct like that.

An alternative to static import would be to `import loc = local;` 
which introduces `loc` but doesn't go further; everything in 
`local` has to be qualified as `loc.*`.


They aren't selective, yeah. But the rationale is good: There's 
not supposed to be any way to import modules with the same path 
so static importing means it's entirely and always unambiguous.


The idea was to static import 'local' (to introduce the 'local' 
name itself into scope), which lets you use its contents only 
fully-qualified and, basically solves your issue. You could still 
`import local;` inside the function to use its contents 
unqualified.


Re: Scoped Imports for Structs/Classes/Template Constraints

2015-09-01 Thread jmh530 via Digitalmars-d-learn

On Tuesday, 1 September 2015 at 19:48:02 UTC, Enamex wrote:


They aren't selective, yeah. But the rationale is good: There's 
not supposed to be any way to import modules with the same path 
so static importing means it's entirely and always unambiguous.


I understand that a static import is always unambiguous. That's 
really the only thing the documentation says about static 
imports. I wonder if there are any other difference.


Consider these three different ways to import std.stdio
import std.stdio;
import std.stdio : writeln;
static import std.stdio;
and suppose writeln is the only function in std.stdio the program 
is using.


In each case, the size of the exe is exactly the same. So 
presumably, the compiler is smart enough to see that 
std.stdio.chunks, for instance, isn't used and not to include in 
the final program. However, there might be a difference in 
compile times (though I don't exactly know how to measure that).


My understanding is that import std.stdio; leads to all of 
std.stdio being compiled, but import std.stdio : writeln leads to 
only writeln being compiled (and anything it depends on). There 
are also faster lookups during compilation, or something, I 
think. Given that the documentation only indicates the difference 
between import std.stdio and static import std.stdio is the 
ambiguous-ness that you point out, I would expect that the time 
to compile would be the same as import std.stdio. Is this correct?


Re: Scoped Imports for Structs/Classes/Template Constraints

2015-09-01 Thread Enamex via Digitalmars-d-learn

On Tuesday, 1 September 2015 at 21:17:10 UTC, jmh530 wrote:

Consider these three different ways to import std.stdio
import std.stdio;
import std.stdio : writeln;
static import std.stdio;
and suppose writeln is the only function in std.stdio the 
program is using.


In each case, the size of the exe is exactly the same. So 
presumably, the compiler is smart enough to see that 
std.stdio.chunks, for instance, isn't used and not to include 
in the final program. However, there might be a difference in 
compile times (though I don't exactly know how to measure that).


My understanding is that import std.stdio; leads to all of 
std.stdio being compiled, but import std.stdio : writeln leads 
to only writeln being compiled (and anything it depends on). 
There are also faster lookups during compilation, or something, 
I think. Given that the documentation only indicates the 
difference between import std.stdio and static import std.stdio 
is the ambiguous-ness that you point out, I would expect that 
the time to compile would be the same as import std.stdio. Is 
this correct?


Oh no. Importing in D is a symbol table import. If you're using a 
module and it's only available in source-format to the compiler, 
then it has to compile the whole module even if you're using just 
one function (because internally the whole module is likely to be 
very tightly coupled, and usually should be, if it's under one 
name).


   import std.stdio; // makes available for calling all symbols 
in std.stdio; compiles module if not pre-compiled and if at least 
one symbol is used (not sure about the last point)
   import std.stdio : writeln; // makes available for calling 
only 'writeln()' from std.stdio; compiles module if not 
pre-compiled
   static import std.stdio; // makes available for calling all 
symbols in std.stdio but only when fully qualified; compiles 
module if not pre-compiled


As I understand it, the only difference between cases with 
different numbers of called symbols from a module is apparent 
during linking, not compilation.


Anyone can shed light on this?


Re: Scoped Imports for Structs/Classes/Template Constraints

2015-09-01 Thread jmh530 via Digitalmars-d-learn

On Monday, 31 August 2015 at 23:36:25 UTC, Enamex wrote:
I'm not sure whether a naked 'local.S' should work; sometimes 
it does and sometimes it doesn't. But an `static import local;` 
then `voidfoo(local.S)` definitely works.


`static import` forces the imported symbols to be fully 
qualified on use. It basically only allows the module to 
recognize the existence of modules outside its package.


Doing `import app: foo;` or even just `import app;` would never 
import `module app;`'s imports unless those imports are public.


`module foo; public static import local; import bazoo;`
`module bar; void fun() { local.S s; } // works
void fun2() { bazoo.B b; } // error`


I'm following some of your post, but not quite all of it 
(particularly the part at the end, and I also think static 
imports can't be selective). Anyway, I was thinking about 
something like below as one possible alternative


struct T
{
import local : S;
void foo(S s)
{
import std.stdio : writeln;
writeln(s.a);
}
}


Re: Scoped Imports for Structs/Classes/Template Constraints

2015-08-31 Thread Enamex via Digitalmars-d-learn

On Monday, 31 August 2015 at 19:10:45 UTC, jmh530 wrote:

module local;

struct S { int a = 2; }

module app;

import local : S;

void foo(S s)
{
import std.stdio : writeln;
writeln(s.a);
}

void bar()
{
import std.stdio : writeln;
import local : S;
S s;
writeln(s.a);
}

void main()
{
S s;
foo(s);
bar();
}


You can't use it with foo(S) because the type is used /outside/ 
the scope of the function, in its head. You have to qualify it ( 
void foo(local.S s) )  or import the type as:


{ import local: S;
void foo(S s) { ... }
}


Re: Scoped Imports for Structs/Classes/Template Constraints

2015-08-31 Thread jmh530 via Digitalmars-d-learn

On Monday, 31 August 2015 at 20:54:53 UTC, Enamex wrote:


You can't use it with foo(S) because the type is used /outside/ 
the scope of the function, in its head. You have to qualify it 
( void foo(local.S s) )  or import the type as:


{ import local: S;
void foo(S s) { ... }
}


I figured the scoping was the issue. Just curious if there was a 
trick around it. The only thing I could think of was just using 
more sub-modules to break up the code by imports. The downside is 
that it might lead to longer compile times.


I'm not sure about how the first local.S resolves things. I had 
been using a selective import for S before. To get the local.S to 
compile, I have to change the import to a normal one. I'm 
concerned about the case where local contains more than just S. 
Suppose I import app : foo; in another module, wouldn't this 
import all of local? Alternately, suppose I create some function 
baz that does not use S in any way, then if I import app : baz, 
then I will inadvertently import local, correct?


The second thing does not compile for me (I had tried that 
already...). I get


app.d(3): Error: declaration expected, not '{'
app.d(10): Error: unrecognized declaration


Re: Scoped Imports for Structs/Classes/Template Constraints

2015-08-31 Thread Enamex via Digitalmars-d-learn

On Monday, 31 August 2015 at 21:22:07 UTC, jmh530 wrote:
I'm not sure about how the first local.S resolves things. I had 
been using a selective import for S before. To get the local.S 
to compile, I have to change the import to a normal one. I'm 
concerned about the case where local contains more than just S. 
Suppose I import app : foo; in another module, wouldn't this 
import all of local? Alternately, suppose I create some 
function baz that does not use S in any way, then if I import 
app : baz, then I will inadvertently import local, correct?


The second thing does not compile for me (I had tried that 
already...). I get


app.d(3): Error: declaration expected, not '{'
app.d(10): Error: unrecognized declaration


I'm not sure whether a naked 'local.S' should work; sometimes it 
does and sometimes it doesn't. But an `static import local;` then 
`voidfoo(local.S)` definitely works.


`static import` forces the imported symbols to be fully qualified 
on use. It basically only allows the module to recognize the 
existence of modules outside its package.


Doing `import app: foo;` or even just `import app;` would never 
import `module app;`'s imports unless those imports are public.


`module foo; public static import local; import bazoo;`
`module bar; void fun() { local.S s; } // works
void fun2() { bazoo.B b; } // error`