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.