www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - is "import std;" a valid approach or a violation of the D programming

reply Steef Boerrigter <sxmboer gmail.com> writes:
I've been using

     import std;

at the top of my code for a while using dmd.

None of the examples in Andrei or Ali's books do this, but 
following the turtles all the way down principle they should also 
be able to go all the way up. (or no?)

Or call me lazy. I get why and how the compiler can more 
efficiently produce code using highly specific imports within 
each context, but I've tested this and it only adds about .3 s to 
my compiles, so why would I bother to try and optimize my compile 
time?

This one-import-rules-all approach saves me a bunch of time 
figuring out which import should go where, so overall, makes 
programming in D much more efficient for my purposes. Either way, 
it seems valid to me and has worked with dmd just fine.

However, gdc does not compile any code using this approach:

     chocolate>gdc ocr.d
     ocr.d:7:8: error: module std is in file 'std.d' which cannot 
be read
         7 | import std;
           |        ^
     import path[0] = 
/usr/lib64/gcc/x86_64-slackware-linux/10.2.0/include/d


My question is now, am I abusing an oversight in dmd when I 
import the entire phobos library, or is it a bug of gdc to *not* 
accept this approach?


Steef
May 06 2021
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 6 May 2021 at 22:27:21 UTC, Steef Boerrigter wrote:
 None of the examples in Andrei or Ali's books do this, but 
 following the turtles all the way down principle they should 
 also be able to go all the way up. (or no?)
The convenience module was simply added after those books were written.
 I've tested this and it only adds about .3 s to my compiles
lol my entire program takes less than that to build total.
 However, gdc does not compile any code using this approach:
gdc also uses an older version of Phobos. The import std thing was only added.... I think last year. It is quite recent.
May 06 2021
prev sibling next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Thursday, 6 May 2021 at 22:27:21 UTC, Steef Boerrigter wrote:
 My question is now, am I abusing an oversight in dmd when I 
 import the entire phobos library, or is it a bug of gdc to 
 *not* accept this approach?
The `std` package is a relatively recent addition (DMD 2.086), and gdc is simply a bit behind on the latest front-end currently. It used to be called `std.experimental.all`, so you could do: ```D static if (__VERSION__ <= 2085) { import std.experimental.all; } else { import std; } ``` Note that it is discouraged to use outside scripts / small applications, because every time a new symbol is added into Phobos, there is potential it could clash with one of your own symbols. For example, say you already imported your own `SumType`, and then `std.sumtype` was added. You now get ambiguous symbol errors because you're importing `std.sumtype` unintentionally.
May 06 2021
next sibling parent Berni44 <someone somemail.com> writes:
On Thursday, 6 May 2021 at 22:36:05 UTC, Dennis wrote:
 Note that it is discouraged to use outside scripts / small 
 applications, because every time a new symbol is added into 
 Phobos, there is potential it could clash with one of your own 
 symbols.
I recently forgot to define a variable called `name` while using `import std`. It still compiled, but I was a little bit surprised by the result. (Can you guess what I got?)
May 06 2021
prev sibling parent reply Berni44 <someone somemail.com> writes:
On Thursday, 6 May 2021 at 22:36:05 UTC, Dennis wrote:
 Note that it is discouraged to use outside scripts / small 
 applications, because every time a new symbol is added into 
 Phobos, there is potential it could clash with one of your own 
 symbols.
The executable is also much larger. I compared ``` import std; void main() { } ``` with ``` void main() { } ``` 2.9 MB vs 860 KB. (I wonder, what rubbish this is, that is put in the first executable.)
May 09 2021
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Sunday, 9 May 2021 at 20:20:15 UTC, Berni44 wrote:
 On Thursday, 6 May 2021 at 22:36:05 UTC, Dennis wrote:
 Note that it is discouraged to use outside scripts / small 
 applications, because every time a new symbol is added into 
 Phobos, there is potential it could clash with one of your own 
 symbols.
The executable is also much larger. I compared ``` import std; void main() { } ``` with ``` void main() { } ``` 2.9 MB vs 860 KB. (I wonder, what rubbish this is, that is put in the first executable.)
It would be nice if we got real selective imports...
May 09 2021
prev sibling parent reply Witold Baryluk <witold.baryluk gmail.com> writes:
On Sunday, 9 May 2021 at 20:20:15 UTC, Berni44 wrote:
 On Thursday, 6 May 2021 at 22:36:05 UTC, Dennis wrote:
 Note that it is discouraged to use outside scripts / small 
 applications, because every time a new symbol is added into 
 Phobos, there is potential it could clash with one of your own 
 symbols.
The executable is also much larger. I compared ``` import std; void main() { } ``` with ``` void main() { } ``` 2.9 MB vs 860 KB. (I wonder, what rubbish this is, that is put in the first executable.)
Another disadvantage of using `import std` is compile time. I often have my projects on `sshfs` file system, that is mounted from a server in a different country. I often mount with default options, with has very short "negative cache" timeout (i.e. lookup was attempted, but didn't found a file), and medium "positive cache" timeout (lookup or read was done, and it did file and a content). At least `gdc` and `ldc2` compilers (and I am sure `dmd` too) do have tendency to try all find files (`.di` and `.d`) for imports in a current working directory first, even if they are imported from a file that is not in the current working directory. Pulling entire `import std;` leads to 514 failed file lookup: ``` ~/mysshmount/Projects/dmt$ strace ldc2 dmt.d 2>&1 | grep -E "^stat\(\"[^/]" stat(".", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 stat("std/typecons.di", 0x7ffc6dadbeb0) = -1 ENOENT (No such file or directory) stat("std/typecons.d", 0x7ffc6dadbeb0) = -1 ENOENT (No such file or directory) stat("std/typecons", 0x7ffc6dadbeb0) = -1 ENOENT (No such file or directory) stat("std/format.di", 0x7ffc6dadbe30) = -1 ENOENT (No such file or directory) stat("std/format.d", 0x7ffc6dadbe30) = -1 ENOENT (No such file or directory) stat("std/format", 0x7ffc6dadbe30) = -1 ENOENT (No such file or directory) stat("object.di", 0x7ffc6dadbdd0) = -1 ENOENT (No such file or directory) stat("object.d", 0x7ffc6dadbdd0) = -1 ENOENT (No such file or directory) stat("object", 0x7ffc6dadbdd0) = -1 ENOENT (No such file or directory) stat("core/internal/vararg/sysv_x64.di", 0x7ffc6dadbcc0) = -1 ENOENT (No such file or directory) stat("core/internal/vararg/sysv_x64.d", 0x7ffc6dadbcc0) = -1 ENOENT (No such file or directory) stat("core/internal/vararg/sysv_x64", 0x7ffc6dadbcc0) = -1 ENOENT (No such file or directory) stat("core/stdc/stdarg.di", 0x7ffc6dadbc20) = -1 ENOENT (No such file or directory) stat("core/stdc/stdarg.d", 0x7ffc6dadbc20) = -1 ENOENT (No such file or directory) stat("core/stdc/stdarg", 0x7ffc6dadbc20) = -1 ENOENT (No such file or directory) stat("core/attribute.di", 0x7ffc6dadbd00) = -1 ENOENT (No such file or directory) stat("core/attribute.d", 0x7ffc6dadbd00) = -1 ENOENT (No such file or directory) stat("core/attribute", 0x7ffc6dadbd00) = -1 ENOENT (No such file or directory) stat("core/internal/hash.di", 0x7ffc6dadbd00) = -1 ENOENT (No such file or directory) stat("core/internal/hash.d", 0x7ffc6dadbd00) = -1 ENOENT (No such file or directory) ... ``` (for a total of 513 such failed lookups) And because `sshfs` has very short "negative caching" timeout. Even running this command again, will be equally slow (`sshfs` will already forgot that this files doesn't exist, and will need to do network operations again to get this information). Using selective imports, not only is better long terms, it is faster in general. In my case, instead of about 10.5s, it finishes in 6.0s. Which is manageable and not annoying to me. (Compiling on a local file system is 1.3s)
May 14 2021
parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Friday, 14 May 2021 at 22:33:24 UTC, Witold Baryluk wrote:
 On Sunday, 9 May 2021 at 20:20:15 UTC, Berni44 wrote:
 [...]
Another disadvantage of using `import std` is compile time. I often have my projects on `sshfs` file system, that is mounted from a server in a different country. I often mount with default options, with has very short "negative cache" timeout (i.e. lookup was attempted, but didn't found a file), and medium "positive cache" timeout (lookup or read was done, and it did file and a content). [...]
`import std;` has always been a convenience feature for D as script language (`rdmd`). It was never intended to be part of a normal project. Normal projects should use selective imports or scoped imports. Using `import.std;` otherwise is a violation of the intent.
May 15 2021
parent reply Witold Baryluk <witold.baryluk gmail.com> writes:
On Saturday, 15 May 2021 at 12:53:37 UTC, Patrick Schluter wrote:
 On Friday, 14 May 2021 at 22:33:24 UTC, Witold Baryluk wrote:
 On Sunday, 9 May 2021 at 20:20:15 UTC, Berni44 wrote:
 [...]
Another disadvantage of using `import std` is compile time. I often have my projects on `sshfs` file system, that is mounted from a server in a different country. I often mount with default options, with has very short "negative cache" timeout (i.e. lookup was attempted, but didn't found a file), and medium "positive cache" timeout (lookup or read was done, and it did file and a content). [...]
`import std;` has always been a convenience feature for D as script language (`rdmd`). It was never intended to be part of a normal project. Normal projects should use selective imports or scoped imports. Using `import.std;` otherwise is a violation of the intent.
I think `import std;` shouldn't be used for scripting. It just makes startup longer (which is important for scripts), and makes you vulnerable to future conflicts with new symbols in Phobos, which is a reality in anything other than most trivial scripts. Sure, it is a good start in rush to start with off, but nothing more.
May 15 2021
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/15/21 9:59 AM, Witold Baryluk wrote:
 I think `import std;` shouldn't be used for scripting. It just makes 
 startup longer (which is important for scripts), and makes you 
 vulnerable to future conflicts with new symbols in Phobos, which is a 
 reality in anything other than most trivial scripts. Sure, it is a good 
 start in rush to start with off, but nothing more.
One reason why import std is expensive is that it instantiates a bunch of templates (even if not used). That can be seen with -vtemplates: https://run.dlang.io/is/MT6hvE I think we can improve on that.
May 15 2021
parent Max Haughton <maxhaton gmail.com> writes:
On Saturday, 15 May 2021 at 16:11:35 UTC, Andrei Alexandrescu 
wrote:
 On 5/15/21 9:59 AM, Witold Baryluk wrote:
 I think `import std;` shouldn't be used for scripting. It just 
 makes startup longer (which is important for scripts), and 
 makes you vulnerable to future conflicts with new symbols in 
 Phobos, which is a reality in anything other than most trivial 
 scripts. Sure, it is a good start in rush to start with off, 
 but nothing more.
One reason why import std is expensive is that it instantiates a bunch of templates (even if not used). That can be seen with -vtemplates: https://run.dlang.io/is/MT6hvE I think we can improve on that.
If anything ever comes of it, the thing Stefan is playing around with (Tasks/Making dmd aware of dependencies inside itself) could make PAYG a science rather than a hack in future - i.e. do more work to understand where you can do nothing instead.
May 15 2021
prev sibling parent Joakim =?UTF-8?B?QnLDpG5uc3Ryw7Zt?= <notfornow dev.null.com> writes:
On Saturday, 15 May 2021 at 13:59:15 UTC, Witold Baryluk wrote:
 I think `import std;` shouldn't be used for scripting. It just 
 makes startup longer (which is important for scripts), and 
 makes you vulnerable to future conflicts with new symbols in 
 Phobos, which is a reality in anything other than most trivial 
 scripts. Sure, it is a good start in rush to start with off, 
 but nothing more.
I love it for scripting. `import std;` and start solving the problem. If startup is a concern I precompile the *script* :) Then later on if the script ever need to grow to a *real* program it is refactoring time and replace `import std;` with what is used. // Joakim B.
May 15 2021
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Thursday, 6 May 2021 at 22:27:21 UTC, Steef Boerrigter wrote:
 I've been using

     import std;

 at the top of my code for a while using dmd.

 None of the examples in Andrei or Ali's books do this, but 
 following the turtles all the way down principle they should 
 also be able to go all the way up. (or no?)
[...]
 However, gdc does not compile any code using this approach:

     chocolate>gdc ocr.d
     ocr.d:7:8: error: module std is in file 'std.d' which 
 cannot be read
         7 | import std;
           |        ^
     import path[0] = 
 /usr/lib64/gcc/x86_64-slackware-linux/10.2.0/include/d


 My question is now, am I abusing an oversight in dmd when I 
 import the entire phobos library, or is it a bug of gdc to 
 *not* accept this approach?
Generally speaking, you cannot import an entire package in D, only individual modules. The reason `import std` works is that recent versions of the D standard library include a [package module][1] for the `std` package. It doesn't work with gdc because the standard library version included with gdc 10.2 is not recent enough to include the `std` package module. [1]: https://dlang.org/spec/module.html#package-module
May 06 2021