On Sunday, 21 May 2017 at 04:08:04 UTC, Vittorio Romeo wrote:
This exact statement applied to C++ before C++11, but the introduction of lambda expression significantly changed the way people write and think about C++. Sometimes syntactic sugar can have huge impact on a language.

Oh absolutely, make no mistake, I would be FOR this addition. I like it and do think it would be worth it in a lot of places.

But, using the struct stuff, we can add some artificial sweetener now:

return bar(lambda!(x, q{ (int y) => x + y }));

You pass the captures first, then a q{} string literal of the lambda. Here's the implementation of that lambda template:



    template lambda(Args...) {
        import std.conv;
        import std.range;
        import std.string;
        string evil() {
                // build the functor
                import std.meta;
                string code = "static struct anon {";
                foreach(i; aliasSeqOf!(iota(0, Args.length-1)))
code ~= "typeof(Args[" ~ to!string(i) ~ "]) " ~ Args[i].stringof ~ ";";

                string func = Args[$-1];
                auto idx = func.indexOf("=>");
                if(idx == -1)
throw new Exception("No => in lambda"); // or we could use one of the other styles

                auto args = func[0 .. idx];
                auto bod  = func[idx + 2 .. $];

code ~= "auto opCall(T...)" ~ args ~ "{ return " ~ bod ~ "; }";

                code ~= "this(T...)(T t) {
                        this.tupleof = t;
                };";

                code ~= "}";
                return code;
        }
        mixin(evil());
        anon lambda() {
                anon a;
                // copy the values in
                a.tupleof = Args[0 .. $-1];
                return a;
        }
    }





Yes, the C++ syntax is still a bit better and can give MUCH nicer error messages, but for short things, this isn't bad.


    foreach(i; 0..5)
    {
        arr ~= () => writeln(i);
    }

so that's actually a long standing bug, but it hasn't been fixed for a long time....

But to work with that, you can do a capture with a wrapper function:

     arr ~= ((i) => delegate() { writeln(i); })(i);

So you define a new function that returns the delegate and pass the argument right there. This technique is common in Javascript.

Or, of course, using the artificial sweetener above, you can do:

arr ~= lambda!(i, q{ writeln(i); });

...assuming the imports are correct to call that library function... so i'll grant the artificial sweetener can leave a bitter aftertaste. (This is a good case to use in a feature request as to why the string mixin trick isn't actually a great replacement!)

Reply via email to