D import idiom compilation time

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Jan 7 21:50:20 UTC 2019


On 1/5/19 5:48 PM, Dgame wrote:
> On Saturday, 5 January 2019 at 21:36:10 UTC, Neia Neutuladh wrote:
>> On Sat, 05 Jan 2019 21:14:37 +0000, Dgame wrote:
>>> I'm curious about that. Would that work or did I miss something?
>>
>> In your version, I might write:
>>
>>   from.std.stdio.thisFunctionDoesNotExist("Hallo");
>>
>> And the error I would get is:
>>
>>   Error: struct FromImpl does not overload ()
> 
> True.. What about:
> 
> ----
> template isModuleImport(string import_)
> {
>      enum isModuleImport = __traits(compiles, { mixin("import ", 
> import_, ";"); });
> }
> 
> template isSymbolInModule(string module_, string symbol)
> {
>      static if (isModuleImport!module_) {
>          enum import_ = module_ ~ ":" ~ symbol;
>          enum isSymbolInModule = __traits(compiles, { mixin("import ", 
> import_, ";"); });
>      } else {
>          enum isSymbolInModule = false;
>      }
> }
> 
> template FailedSymbol(string symbol, string module_)
> {
>      auto FailedSymbol(Args...)(auto ref Args args)
>      {
>          assert(0, "Symbol \"" ~ symbol ~ "\" not found in " ~ module_);
>      }
> }
> 
> struct FromImpl(string module_)
> {
>      template opDispatch(string symbol)
>      {
>          static if (isSymbolInModule!(module_, symbol)) {
>              mixin("import ", module_, "; alias opDispatch = ", symbol, 
> ";");
>          } else {
>              static if (module_.length == 0) {
>                  enum opDispatch = FromImpl!(symbol)();
>              } else {
>                  enum import_ = module_ ~ "." ~ symbol;
>                  static if (isModuleImport!import_) {
>                         enum opDispatch = FromImpl!(import_)();
>                  } else {
>                      alias opDispatch = FailedSymbol!(symbol, module_);
>                  }
>              }
>          }
>      }
> }
> 
> enum from = FromImpl!null();
> 
> void main()
> {
>      from.std.stdio.writeln("Hallo");
>      auto _ = from.std.datetime.stopwatch.AutoStart.yes;
>      from.std.stdio.thisFunctionDoesNotExist("Hallo");
>      from.std.stdio.thisFunctionDoesNotExist(42);
> }
> ----
> 
> Output:
> 
> ----
> Hallo
> core.exception.AssertError at onlineapp.d(20): Symbol 
> "thisFunctionDoesNotExist" not found in std.stdio
> ----------------
> ??:? _d_assert_msg [0x3c00dc54]
> onlineapp.d:20 pure nothrow @nogc @safe void 
> onlineapp.FailedSymbol!("thisFunctionDoesNotExist", 
> "std.stdio").FailedSymbol!(immutable(char)[]).FailedSymbol(immutable(char)[]) 
> [0x3c00ceac]
> onlineapp.d:52 _Dmain [0x3c00c8c3]
> ----

This is pretty awesome.

I ran a couple of experiments and the idiom seems to be lazy as 
expected, e.g. in the declaration:

void fun(T)() if (from.std.traits.isIntegral!T)
{
     from.std.stdio.writeln("Hallo");
}

neither std.traits nor std.stdio gets loaded if fun is not instantiated.

I took the liberty to ask Razvan Nitu to look into fixing 
https://issues.dlang.org/show_bug.cgi?id=17181.

I also asked Eduard Staniloiu to investigate using this idiom internally 
in Phobos so as to accumulate some experience with it. Dgame's 
implementation is a good start.

Since the implementation would (initially at least) be private, the 
presence of "from" in documentation would be awkward. So I suggest the 
glorious hack:

alias std = from.std;

so then things like std.traits.isIntegral and 
std.algorithm.comparison.min resolve and auto-load properly, while also 
standing beautifully in the documentation.


Andrei


More information about the Digitalmars-d mailing list