On 01.08.19 22:23, Matt wrote:
Version 4 does not work when PairedA.previous is null. I'd love to understand why.

[...]

auto myFilter(R1, R2)(R1 a, R2 b)
{
     import std.algorithm : filter, canFind;
     return a.filter!(c => b.canFind(c));
}

struct A
{
     uint[] starts, stops;

     import std.range : ForwardRange, inputRangeObject;
     import std.typecons : Tuple;
     ForwardRange!(Tuple!(uint,uint)) intervalRange() @property
     {
         import std.algorithm : map;
         import std.range : zip;
         import std.typecons : tuple;
        return zip(starts,stops).map!(a => tuple(a[0],a[1])).inputRangeObject;
     }
}

struct PairedA
{
[...]
     //version 4
     auto uniqIntervals() @property
     {
         import std.range : choose;
         import std.algorithm : filter, canFind;
         return choose(previous is null,
             primary.intervalRange,
             primary.intervalRange
                 .myFilter(previous.intervalRange));
     }

     A primary;
     A* previous;
}

`choose`'s parameters aren't lazy. So the second argument is evaluated even when `previous is null`. That means `intervalRange` is called on a null `previous`. And that fails, of course, because `intervalRange` can't access `starts` or `stops` when `this` is null.

Reply via email to