Thread overview
@nogc closures
Aug 05, 2018
vit
Aug 05, 2018
Alex
Aug 05, 2018
vit
Aug 05, 2018
Paul Backus
August 05, 2018
It's possible create something like this without errors?

void main()@nogc{   //Error: function `app.main` is `@nogc`
                    //  yet allocates closures with the GC
    import std.experimental.all;

    const int j = 2;
    int i = 0;
    const int[3] tmp = [1, 2, 3];

    tmp[]
        .filter!((x)scope => x == j)    ///main.__lambda1 closes over variable j
        .each!((x)scope => i = x);
}
August 05, 2018
On Sunday, 5 August 2018 at 09:20:21 UTC, vit wrote:
> It's possible create something like this without errors?
>
> void main()@nogc{   //Error: function `app.main` is `@nogc`
>                     //  yet allocates closures with the GC
>     import std.experimental.all;
>
>     const int j = 2;
>     int i = 0;
>     const int[3] tmp = [1, 2, 3];
>
>     tmp[]
>         .filter!((x)scope => x == j)    ///main.__lambda1 closes over variable j
>         .each!((x)scope => i = x);
> }

No, at least as I understand it.
https://issues.dlang.org/show_bug.cgi?id=17841

But you can define a struct, with the needed j and i are stored, and some functions within, which performs map reduce logic you need.
August 05, 2018
On 8/5/18 5:20 AM, vit wrote:
> It's possible create something like this without errors?
> 
> void main()@nogc{   //Error: function `app.main` is `@nogc`
>                      //  yet allocates closures with the GC
>      import std.experimental.all;
> 
>      const int j = 2;
>      int i = 0;
>      const int[3] tmp = [1, 2, 3];
> 
>      tmp[]
>          .filter!((x)scope => x == j)    ///main.__lambda1 closes over variable j
>          .each!((x)scope => i = x);
> }

The issue is that filter returns a struct with the lambda in it. (the FilterRange). So the compiler can't deduce that the lambda never escapes.

Note, in your toy example, you can fix it by making j an enum, but I'm assuming this isn't possible in the real code.

-Steve
August 05, 2018
On Sunday, 5 August 2018 at 10:57:32 UTC, Steven Schveighoffer wrote:
> On 8/5/18 5:20 AM, vit wrote:
>> It's possible create something like this without errors?
>> 
>> void main()@nogc{   //Error: function `app.main` is `@nogc`
>>                      //  yet allocates closures with the GC
>>      import std.experimental.all;
>> 
>>      const int j = 2;
>>      int i = 0;
>>      const int[3] tmp = [1, 2, 3];
>> 
>>      tmp[]
>>          .filter!((x)scope => x == j)    ///main.__lambda1 closes over variable j
>>          .each!((x)scope => i = x);
>> }
>
> The issue is that filter returns a struct with the lambda in it. (the FilterRange). So the compiler can't deduce that the lambda never escapes.
>
> Note, in your toy example, you can fix it by making j an enum, but I'm assuming this isn't possible in the real code.
>
> -Steve

Yes, it isn't possible.
I modify filter a and map from std.algorithm:

void main()@nogc{
	import std.experimental.all;
	const int j = 2;
	int i = 0;
	const int[3] tmp = [1, 2, 3];
	tmp[]
	    .xfilter!((x, j) => x == j)(j)
            .xmap!((x, j) => x * j)(j)
	    .each!((x) => i = x);
}

full code: https://dpaste.dzfl.pl/15664d6da5c8
August 05, 2018
On 8/5/18 8:23 AM, vit wrote:
> On Sunday, 5 August 2018 at 10:57:32 UTC, Steven Schveighoffer wrote:
>> On 8/5/18 5:20 AM, vit wrote:
>>> It's possible create something like this without errors?
>>>
>>> void main()@nogc{   //Error: function `app.main` is `@nogc`
>>>                      //  yet allocates closures with the GC
>>>      import std.experimental.all;
>>>
>>>      const int j = 2;
>>>      int i = 0;
>>>      const int[3] tmp = [1, 2, 3];
>>>
>>>      tmp[]
>>>          .filter!((x)scope => x == j)    ///main.__lambda1 closes over variable j
>>>          .each!((x)scope => i = x);
>>> }
>>
>> The issue is that filter returns a struct with the lambda in it. (the FilterRange). So the compiler can't deduce that the lambda never escapes.
>>
>> Note, in your toy example, you can fix it by making j an enum, but I'm assuming this isn't possible in the real code.
>>
>> -Steve
> 
> Yes, it isn't possible.
> I modify filter a and map from std.algorithm:
> 
> void main()@nogc{
>      import std.experimental.all;
>      const int j = 2;
>      int i = 0;
>      const int[3] tmp = [1, 2, 3];
>      tmp[]
>          .xfilter!((x, j) => x == j)(j)
>              .xmap!((x, j) => x * j)(j)
>          .each!((x) => i = x);
> }
> 
> full code: https://dpaste.dzfl.pl/15664d6da5c8

Cool! Consider writing a PR and see if it's acceptable to put into Phobos.

-Steve
August 05, 2018
On Sunday, 5 August 2018 at 12:23:17 UTC, vit wrote:
> Yes, it isn't possible.
> I modify filter a and map from std.algorithm:
>
> void main()@nogc{
> 	import std.experimental.all;
> 	const int j = 2;
> 	int i = 0;
> 	const int[3] tmp = [1, 2, 3];
> 	tmp[]
> 	    .xfilter!((x, j) => x == j)(j)
>             .xmap!((x, j) => x * j)(j)
> 	    .each!((x) => i = x);
> }
>
> full code: https://dpaste.dzfl.pl/15664d6da5c8

You can do it without modifying existing functions if you use `zip`:

https://run.dlang.io/is/IKUvEf