August 26, 2016
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.