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