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);
}