Jump to page: 1 2
Thread overview
blocks with attributes vs inlined lambda
Jun 08, 2013
monarch_dodra
Jun 08, 2013
monarch_dodra
Jun 18, 2013
Robert Clipsham
Jun 08, 2013
deadalnix
Jun 08, 2013
monarch_dodra
Jun 08, 2013
deadalnix
Jun 08, 2013
Idan Arye
Jun 08, 2013
monarch_dodra
Jun 08, 2013
monarch_dodra
Jun 17, 2013
monarch_dodra
Jun 18, 2013
deadalnix
Jun 18, 2013
Kenji Hara
Jun 18, 2013
monarch_dodra
Jun 19, 2013
monarch_dodra
Jun 30, 2013
Timon Gehr
Jul 01, 2013
deadalnix
Aug 18, 2013
monarch_dodra
Aug 19, 2013
Kenji Hara
Aug 19, 2013
monarch_dodra
June 08, 2013
I remember think that being able to mark specific parts of code with certain attributes, inside a block, could be very useful.

for example:

--------
void foo()
{
   //Code

   /Critical section
   nothrow {
       //code here can't throw
   }

   //More code
}
--------

I have since learned that you can do this with lambda's instead, declaring and calling them in a single line:

--------
void foo()
{
   //Code

   /Critical section
   () nothrow
{
       //code here can't throw
   }

   //More code
}
--------
June 08, 2013
EDIT: Sorry: stupid computer sent before I was finished. I was saying...

I have since learned that you can do this with lambda's
instead, declaring and calling them in a single line:

--------
void foo()
{
   //Code

   //Critical section
   () nothrow //declaration
   { //body
       //code here can't throw
   } () //actual call

    //More code
}
--------

This works. This feature is appearing with higher frequency inside phobos, which is proof it is a good feature, and that it has uses, and is becoming popular.

My beef though is that the syntax is a bit opaque, and not really idiomatic. It looks more like a hacker's trick than a real language feature. It's not something you'd do "naturally". At least, I know a beginner may not feal comfortable with this.

Given that users are now actually doing this, that we have proof it works and is a useful feature, shouldn't we push to have actual blocks with attributes in the language?

I think we should... Thoughts?
June 08, 2013
On Saturday, 8 June 2013 at 14:52:23 UTC, monarch_dodra wrote:
> I remember think that being able to mark specific parts of code with certain attributes, inside a block, could be very useful.
>
> for example:
>
> --------
> void foo()
> {
>    //Code
>
>    /Critical section
>    nothrow {
>        //code here can't throw
>    }
>
>    //More code
> }
> --------
>
> I have since learned that you can do this with lambda's instead, declaring and calling them in a single line:
>
> --------
> void foo()
> {
>    //Code
>
>    /Critical section
>    () nothrow
> {
>        //code here can't throw
>    }
>
>    //More code
> }
> --------

Sound like a nice idiom. Why is the first set of () needed ? Can we change the grammar to remove them ?
June 08, 2013
On Saturday, 8 June 2013 at 15:56:47 UTC, deadalnix wrote:
>
> Sound like a nice idiom. Why is the first set of () needed ? Can we change the grammar to remove them ?

It's because you are actually declaring a lambda that takes no arguments, and has no name, and contains a body. BTW, you quoted my incomplete code, the correct code I wanted to post was:

() nothrow {//anonymous lambade declaration
    //Body of the lambde
}() //actual call to lambda

I'd want to be able to do this, without either the first or last set of (). The required change of grammar would mean there'd be no lambda at all afterwards.
June 08, 2013
On Saturday, 8 June 2013 at 16:13:28 UTC, monarch_dodra wrote:
> On Saturday, 8 June 2013 at 15:56:47 UTC, deadalnix wrote:
>>
>> Sound like a nice idiom. Why is the first set of () needed ? Can we change the grammar to remove them ?
>
> It's because you are actually declaring a lambda that takes no arguments, and has no name, and contains a body. BTW, you quoted my incomplete code, the correct code I wanted to post was:
>
> () nothrow {//anonymous lambade declaration
>     //Body of the lambde
> }() //actual call to lambda
>
> I'd want to be able to do this, without either the first or last set of (). The required change of grammar would mean there'd be no lambda at all afterwards.

{} is a lambda already. The first set of () is optional.
June 08, 2013
On Saturday, 8 June 2013 at 16:21:26 UTC, deadalnix wrote:
> On Saturday, 8 June 2013 at 16:13:28 UTC, monarch_dodra wrote:
>> On Saturday, 8 June 2013 at 15:56:47 UTC, deadalnix wrote:
>>>
>>> Sound like a nice idiom. Why is the first set of () needed ? Can we change the grammar to remove them ?
>>
>> It's because you are actually declaring a lambda that takes no arguments, and has no name, and contains a body. BTW, you quoted my incomplete code, the correct code I wanted to post was:
>>
>> () nothrow {//anonymous lambade declaration
>>    //Body of the lambde
>> }() //actual call to lambda
>>
>> I'd want to be able to do this, without either the first or last set of (). The required change of grammar would mean there'd be no lambda at all afterwards.
>
> {} is a lambda already. The first set of () is optional.

Actually, the first set of `()` is required because of the `nothrow`. You can't write:

    nothrow {
        //body
    }();

because the `nothrow` in lambdas needs to be placed after the argument list - so you need an argument list.
June 08, 2013
On Saturday, 8 June 2013 at 16:21:26 UTC, deadalnix wrote:
>
> {} is a lambda already. The first set of () is optional.

Oh Yeah. Didn't know that. You learn something new every day.

...but for that to work, (it seems) you have actually store or pass the lambda, or all the parser sees is a plain "block".

-------
void main()
{
    int i;
    auto y = {++i;}; //lambde (not called)
    {++i;};          //simple block
    (){++i;}();      //inline lambda call
    writeln(i); //prints 2
}
-------
June 08, 2013
On Saturday, 8 June 2013 at 17:27:48 UTC, monarch_dodra wrote:
> On Saturday, 8 June 2013 at 16:21:26 UTC, deadalnix wrote:
>>
>> {} is a lambda already. The first set of () is optional.
>
> Oh Yeah. Didn't know that. You learn something new every day.
>
> ...but for that to work, (it seems) you have actually store or pass the lambda, or all the parser sees is a plain "block".

Improved example:

-------
void main()
{
    int i;
    auto y = {++i;}; //lambde (not called)
    {++i;};          //simple block
    (){++i;}();      //inline lambda call
//  {++i;}();        //Un-recognized
    writeln(i); //prints 2
}
-------

June 17, 2013
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.

# 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.

# 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...

----------------
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've decided to write a DIP for this.
June 18, 2013
On Monday, 17 June 2013 at 19:05:07 UTC, monarch_dodra wrote:
> # 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'
>

In case of lambda, purity does the wrong thing. The behavior is bogous.
« First   ‹ Prev
1 2