Patterns to avoid GC with capturing closures?

vit vit at vit.vit
Sun Aug 26 06:08:39 UTC 2018


On Friday, 24 August 2018 at 15:18:13 UTC, Peter Alexander wrote:
> Consider this code, which is used as an example only:
>
> auto scaleAll(int[] xs, int m) {
>   return xs.map!(x => m * x);
> }
>
> As m is captured, the delegate for map will rightly allocate 
> the closure in the GC heap.
>
> In C++, you would write the lambda to capture m by value, but 
> this is not a facility in D.
>
> I can write scaleAll like this:
>
> auto scaleAll(int[] xs, int m) @nogc {
>   return repeat(m).zip(xs).map!(mx => mx[0] * mx[1]);
> }
>
> So that repeat(m) stores m, but it is quite hacky to work like 
> this.
>
> I could write my own range that does this, but this is also not 
> desirable.
>
> Are there any established patterns, libraries, or language 
> features that can help avoid the GC allocation in a principled 
> way here?

I try pack/unpack solution, but it looks horrible.
Problem is when every part of chain (filter, map, ...) need 
capture different variables.
I implement modified version of algorithm (filter, map, until, 
tee): https://dpaste.dzfl.pl/929a7af4e87f

You don't need reimplement all of std.algorithm, only parts which 
can be in the middle of chain, things like any, all, each, count 
can be ignored.


example:
void main()@nogc{
     import std.algorithm : any;
     import std.range : iota;
     import util.algorithm : map, filter;

     const int
		a = 1,
		b = 2,
		c = 3;
	
     const x = iota(0, 10)
         .map!((x, i) => x*i)(a)   ///map!((x) => x*a)
         .map!((x, i) => x*i)(b)   ///map!((x) => x*b)
         .filter!((x, i) => x%i)(c)///filter!((x) => x%c)
         .any!(x => x % c);

     assert(x == true);

}


More information about the Digitalmars-d-learn mailing list