1 /**
2 Lazy import symbols
3 */
4 module bolts.from;
5
6 /**
7 Encompases the from import idiom in an opDispatch version
8
9 Since:
10 - 0.12.0
11
12 See_Also:
13 <li> https://dlang.org/blog/2017/02/13/a-new-import-idiom/
14 <li> https://forum.dlang.org/thread/gdipbdsoqdywuabnpzpe@forum.dlang.org
15 */
16 enum from = FromImpl!null();
17
18 ///
19 unittest {
20 // Call a function
21 auto _0 = from.std.algorithm.map!"a"([1, 2, 3]);
22 // Assign an object
23 auto _1 = from.std.datetime.stopwatch.AutoStart.yes;
24
25 // compile-time constraints
26 auto length(R)(R range) if (from.std.range.isInputRange!R) {
27 return from.std.range.walkLength(range);
28 }
29
30 assert(length([1, 2]) == 2);
31 }
32
33 private template CanImport(string moduleName) {
34 enum CanImport = __traits(compiles, { mixin("import ", moduleName, ";"); });
35 }
36
37 private template ModuleContainsSymbol(string moduleName, string symbolName) {
38 enum ModuleContainsSymbol = CanImport!moduleName && __traits(compiles, {
39 mixin("import ", moduleName, ":", symbolName, ";");
40 });
41 }
42
43 private struct FromImpl(string moduleName) {
44 template opDispatch(string symbolName) {
45 static if (ModuleContainsSymbol!(moduleName, symbolName)) {
46 mixin("import ", moduleName,";");
47 mixin("alias opDispatch = ", symbolName, ";");
48 } else {
49 static if (moduleName.length == 0) {
50 enum opDispatch = FromImpl!(symbolName)();
51 } else {
52 enum importString = moduleName ~ "." ~ symbolName;
53 static assert(
54 CanImport!importString,
55 "Symbol \"" ~ symbolName ~ "\" not found in " ~ modueName
56 );
57 enum opDispatch = FromImpl!importString();
58 }
59 }
60 }
61 }
62
63 unittest {
64 static assert(!__traits(compiles, { from.std.stdio.thisFunctionDoesNotExist(42); }));
65 }