Source expression passed to a lazy parameter

Simen Kjærås simen.kjaras at gmail.com
Mon Apr 9 09:20:42 UTC 2018


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


More information about the Digitalmars-d-learn mailing list