So this is a small thing but I find it definitely useful in my
own ranges and wished the ranges in phobos did this.
A lot of ranges in phobos take an alias to a function and somehow
use that to generate the output range, for example map. But it
can be annoying when your map function needs extra data to
perform the map. Example...
auto foo(R)(R range, int x) {
return range.map!((v)=>(v+x));
}
That works perfectly well because it will allocate a closure and
make it work. But if foo was @nogc then it would fail. If you are
trying to avoid the gc, the basic range functions get pretty
annoying to use.
One thing I have started doing with any of my range generators
that take an alias to a function is to have an extra ARGS...
argument tacked in on the end. Then the range that gets generated
will save the extra args into the resulting range struct and pass
them back into the alias function whenever it needs to be called.
Example:
auto RangeGenerator(alias pred, ARGS...)(ARGS args) {
// Range struct
struct Range {
private ARGS extra;
// range implementation that somehow calls pred
// If pred is normally takes a single argument, similar
to map, like pred(item)
// then I would instead call pred(item, extra)
}
Range r;
r.extra = args;
/// any other setup
return r;
}
I use this alot, for example I have an octree implementation that
provides range interface to iterate the items that lie in a
specific region in space. The region is defined by a region
function that takes an axis aligned bounding box and returns true
or false if it lies in the region. But a lot of times the region
function needs extra arguments to do the test, but I can't rely
on gc allocated closures to make it possible. So instead I just
pass the extra data into the range generator and have it saved
into the resulting range struct. It works extremely well and
means I don't need to use the GC.
I don't know if anyone else ever has this problem but I just
thought I would share.