2013/6/18 monarch_dodra <monarchdodra@gmail.com>
On Saturday, 8 June 2013 at 15:56:47 UTC, deadalnix wrote:
On Saturday, 8 June 2013 at 14:52:23 UTC, monarch_dodra wrote:

Sound like a nice idiom. Why is the first set of () needed ? Can we change the grammar to remove them ?

I've been playing around with this idiom some more, and found some pretty serious limitations:

# Scoped block:
Using a lambda functions creates a new scope. Having a "true" labeled block, just like static ifs, should not create a new scope. This is relevant if you want to make sure a constructor or destructor is nothrow, for example (destructor could be handled via a simple attribute followed by a colon. eg:

void foo()
{
    nothrow {
        Sentinel s; //declare sentinel
    }

    code_goes_here

    nothrow:
        clean_up_goes_here_code
        destructors_are_nothrow
}

A lambda would not allow these two constructs.

In D, variable declaration with default construction is always nothrow. 
So, enclosing the declaration of s by nothrow block is unnecessary.

For nothrow destruction, you can add following static assert in foo().

    static assert(__traits(compiles, ()nothrow{ Sentinel s; }), "Sentinel dtor is not nothrow");

# Purity
Because a lambda needs to access the frame, any function using the lambda trick can't be made pure:
void foo(T)(T a) @safe
{
    (){
        ++a;
    }();
}
Error: pure function 'main.foo' cannot call impure function literal '__lambda1'

The workaround is to explicitly pass the arguments, *preferably*, shadowing them for clarity:
void foo(int a) pure
{
    (ref int a){
        ++a;
    }(a);
}
This is already *much* less convenient. Imagine if the block needed to access 3, 5 or even more variabes ! Also, if one of those variables is declared as "auto", then you bring in the "ref typeof(a) a" ugliness. Just no.

This is a compiler bug, and I recently fixed it in git master. Explicit argument passing does not need anymore.
  
# Performance
I haven't actually tested this one, but I'd be inclined to think there is a performance hit for non-release and non-inline builds. inline builds *may* optimize it away, but I'm not sure...

Inlining should remove performance penalty. Nobody holds the immediately called lambda, so it should be treated as a 'scope delegate'. For that, we would need to add a section in language spec to support it.
 
----------------
So my conclusion is that the lambda tric is a partial workaround. We'd need real support for being able to have specific qualification inside bodies.

I don't think so. We can sufficiently use lambda for the "attribute block".

Kenji Hara