Lambda surprise

Jean-Louis Leroy jl at leroy.nyc
Sat Feb 8 06:21:50 UTC 2020


While implementing support for parameter storage classes in my 
openmethods library, I ran into a puzzling error.

While massaging code I came up with something like this:

// dmd -c surprise.d
import std.algorithm;
import std.range;

struct Method {
   static string foo() {
     enum foo = [ "a", "b" ].map!(x => x ~ x).join(":");
     return foo;
   }
}

pragma(msg, Method.foo()); // aa:bb

Now this is clearly a compile time constant, so I thought I would 
make it simpler and more explicit:

struct Method {
   enum foo = [ "a", "b" ].map!(x => x ~ x).join(":");
}

...which got me this error:
/home/jll/dlang/dmd-2.085.0/linux/bin64/../../src/phobos/std/algorithm/iteration.d(475): Error: `this.__lambda2` has no value

It took me a while to realize that the root of the problem was 
that the lambda was trying to capture `this`. While fiddling I 
threw in a `static` in front of `enum`:

struct Method {
   static enum foo = [ "a", "b" ].map!(x => x ~ x).join(":");
}

...and I got a more useful error message:
/home/jll/dlang/dmd-2.085.0/linux/bin64/../../src/phobos/std/algorithm/iteration.d(470): Error: function `surprise.Method.map!((x) => x ~ x).map!(string[]).map` need `this` to access member `map`

Thus the first version works because the lambda is formed inside 
a static method. This works as well:

struct Method {
   static string stutter(string s) { return s ~ s; }
   enum foo = [ "a", "b" ].map!(stutter).join(":");
}


I wonder:

1/ Could the error message could be made more explicit in my 
first attempt at making the expression an `enum`?

2/ Is the lambda capturing `this` inside a class, even if it is 
not referenced, a documented behavior? Is it the right thing to 
do?



More information about the Digitalmars-d mailing list