On Monday, 9 April 2018 at 08:27:50 UTC, Per Nordlöw wrote:
Is it possible to get the source expression sent to a lazy function?

Nope. Something along the lines of __traits(getSource, arg) has been discussed occasionally.

For lazy what you're asking is impossible, since the compiler doesn't know which actual arguments have been passed. show(1+2) will look absolutely identical to show(3), will look identical to show(myVarWithValue3).

Now, there are some things you can do. Notably, lambdas are included verbatim in templated type names, which we can exploit.

struct S(alias fn) {}
void show(alias fn)() {
    import std.stdio;
    writeln(S!fn.stringof[18..$-1], ": ", fn());
}

unittest {
    show!(()=>1+2); // prints "3: 3"
}

As we can see, it optimizes '1+2' to become 3, so it's not perfect.

This also works for lambdas that include local variables:

unittest {
    int i = 13;
    show!(() => i+2); // Prints "i + 2: 15"
}

However, it fails for lambdas that take arguments:

struct S(alias fn) {}
void show(alias fn, T...)(T args) {
    import std.stdio;
    writeln(S!fn.stringof[18..$-1], ": ", fn(args));
}

unittest {
    show!(a => a+2)(3); // Fails to compile
}

The reason this fails is the lambda's textual representation decays to '__lambda1'.

There is however still something we can do, but things get even less flexible:

struct show(alias fn) {
    static void opCall(T...)(T args) {
        import std.stdio, std.string;
        enum s = show.stringof;
        enum i = s.indexOf("=>");
        writeln(s[i+3..$-1], ": ", fn(args));
    }
}

unittest {
    show!(a => a+2)(3); // Prints "a + 2: 5"
}

--
  Simen

Reply via email to