Why does choose not work here
Matt
gamblemj at gmail.com
Thu Aug 1 20:23:24 UTC 2019
I'm having some trouble with a "Program exited with code
-1073741819" error in some code I'm writing and I would
appreciate any help/insight.
The problem stems from some incompatibility between the Phobos
function "choose" and the template function "myFilter" which
returns a range. The code below is a simplified version of what
I'm trying to do. myFilter is a dummy/stand-in function that
highlights the error in my program (i.e. My function is not
simply a filter; it is much more complicated but unnecessary to
highlight my problem). In PairedA, sometimes previous will be
null. I need the uniqIntervals member function to do the right
thing depending on if previous is null or not. In an ideal
situation uniqIntervals would return a forward range where the
work would be done in a lazy fashion.
Version 1 works but is not lazy and does not use choose.
Version 2 works but requires converting the ranges to
ForwardRange classes, (I'd prefer to not use an unnecessary level
of indirection).
Version 3 uses the Phobos function filter which works inside
choose (but there is no Phobos function that can actual do why
myFilter stands in for. It's just interesting that the Phobos
function works where myFilter doesn't as they are both template
functions.
Version 4 does not work when PairedA.previous is null. I'd love
to understand why.
I'd also love to some one to show me what the best way to do this
would be. If version 2 is the best I can do, I'll live with it.
Thanks so much, the code is below:
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 1
// auto uniqIntervals() @property
// {
// import std.array : array;
// if (previous is null) return primary.intervalRange.array;
// return primary.intervalRange
// .myFilter(previous.intervalRange).array;
// }
//version 2
// import std.range : ForwardRange, inputRangeObject;
// import std.typecons : Tuple;
// ForwardRange!(Tuple!(uint,uint)) uniqIntervals() @property
// {
// if (previous is null) return
primary.intervalRange.inputRangeObject;
// return primary.intervalRange
// .myFilter(previous.intervalRange).inputRangeObject;
// }
//version 3
// auto uniqIntervals() @property
// {
// import std.range : choose;
// import std.algorithm : filter, canFind;
// return choose(previous is null,
// primary.intervalRange,
// primary.intervalRange
// .filter!(a => previous.intervalRange.canFind(a)));
// }
//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;
}
unittest
{
uint[] startsA = [1,100,1000,10000];
uint[] stopsA = [2,200,2000,20000];
uint[] startsB = [1,100];
uint[] stopsB = [2,200];
auto a1 = A(startsA, stopsA);
auto a2 = A(startsB, stopsB);
auto p = PairedA(a1, &a2);
auto p2 = PairedA(a1, null);
import std.stdio : writeln;
writeln(p.uniqIntervals);//always works
writeln(p2.uniqIntervals);//Program exited with code -1073741819
for version 4
}
More information about the Digitalmars-d-learn
mailing list