www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - nogc closures

reply vit <vit vit.vit> writes:
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);
}
Aug 05 2018
next sibling parent Alex <sascha.orlov gmail.com> writes:
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.
Aug 05 2018
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
Aug 05 2018
parent reply vit <vit vit.vit> writes:
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
Aug 05 2018
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
Aug 05 2018
prev sibling parent Paul Backus <snarwin gmail.com> writes:
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
Aug 05 2018