Search code examples
d

Returning a filtered range


I'm looking at filtering ranges, and getting a little confused. In D, I can write this code:

import std.stdio;
import std.range;
import std.algorithm;

auto filterNums(int[] vals)
{
    int limit = 3;
    return filter!(n => n >limit)(vals);
}

int main()
{
    int[] nums = [1,2,3,4,5];

    auto flt = filterNums(nums);

    foreach(n;flt)
    {
        writeln(n);
    }

    return 0;
}

which gives the expected output of:

4
5

But this doesn't seem to be terribly safe code. If the filter is lazy evaluating, how does it know that limit is 3, once the local variable goes out of scope? Is my code just lucky that nothing else has over-ridden limit in memory? Also is the passed variable nums a reference, or a copied value: if a value, is the filter making its own copy?

Or perhaps I am not using filter in the correct way?


Solution

  • int is a value type, so the filter lambda receives a copy of it. If there were any scoping issues, the compiler would warn you.

    int[] nums is a dynamic array managed by D's runtime. It consists of two parts: a value part, which contains its length and a pointer, which points to the dynamic part on the heap (where the ints are stored). The length and pointer itself are passed by value, which means appending or removing will not affect the original, but editing an element e.g. vals[1] = 1 would. To pass all of it by reference, you would use

    filterNums(ref int[] vals).

    Either way, the garbage collector keeps it around as long as it's needed, in this case it is stored in the filter construct.