| |
| Posted by Matt | PermalinkReply |
|
Matt
| 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
}
|