On Wednesday, 18 September 2019 at 12:03:28 UTC, berni wrote:
The following code doesn't compile:

import std.stdio;

void main()
{
   import std.complex: abs, complex;
   import std.math: abs;

   auto a = complex(1.0,1.0);
   auto b = 1.0;

   writeln(abs(a));
   writeln(abs(b));
}

The error message depends on the order of the two import statements. Seems like the second import is actually ignored.

    import std.complex: abs, complex;

Is treated by the compiler as if you'd written something somewhat like this:

    static import std.complex;
    alias abs = std.complex.abs;
    alias complex = std.complex.complex;

When you add

    import std.math: abs;

It's treated like:

    static import std.math;
    alias abs = std.math.abs;

In other words, we have two aliases with the same name inside a function scope, and the compiler can't do that (try doing it explicitly, as in the 'treated like' sections above - you'll get a compilation error). This is related to why you can't have overloaded nested functions:

    unittest {
        void fun() {}
        void fun(int i) {} // declaration fun is already defined
    }

How to resolve this, though? The simplest solution is to not use selective imports:

    import std.math;
    import std.complex;

    writeln(abs(complex(1.0,1.0)));
    writeln(abs(1.0));

If you absolutely can't contaminate the scope with all the unused symbols in std.math and std.complex, you *can* do this:

import std.stdio;

unittest {
    import std.complex : complex;
    static import std.math;

    alias abs = MergeOverloads!(std.complex.abs, std.math.abs);

    auto a = complex(1.0,1.0);
    auto b = 1.0;

    writeln(abs(a));
    writeln(abs(b));
}

template MergeOverloads(T...) {
    alias MergeOverloads = T[0];
    static if (T.length > 1) {
        alias MergeOverloads = MergeOverloads!(T[1..$]);
    }
}

I would however label that a horrible hack.

FWIW, I've filed this issue: https://issues.dlang.org/show_bug.cgi?id=20226

--
  Simen

Reply via email to