Feasible Idea?: Range Tester
Nick Sabalausky
SeeWebsiteToContactMe at semitwist.com
Thu Mar 21 11:43:25 PDT 2013
On Thu, 21 Mar 2013 11:04:31 -0700
"H. S. Teoh" <hsteoh at quickfur.ath.cx> wrote:
>
> > - Calling popFront and then front returns the next element.
>
> How do you know if something is the "next element"? What if the range
> is repeat(1)?
>
>
> > - If range has length, then 'empty' returns true IFF popFront has
> > been called at least 'myRange.length' times.
>
> This should also be easy to test. But it requires the ability to
> instantiate the range with some given number of elements. So you still
> need a range-specific function to create the range in the first place.
>
What I had in mind was something like:
void testForwardRange(R, E)(R range, E[] content)
{
// Deliberately not contraints, because this *is* a test, after all.
// *Or* maybe it just auto-detects range type and leaves it
// up to the user to check for "isForwardRange!R" or whatever.
static assert(isForwardRange!R);
static assert(is(ElementTypeOf!R == E));
static if(hasLength!R)
assert(range.length == content.length);
foreach(i; 0...content.length)
{
assert(range.front == content[i]);
range.popFront();
}
// More tests
}
unittest{
testForwardRange(createMyRangeSomehow(), [...expected elements...]);
}
>
> > - Calling popFront on an empty range throws a RangeError.
>
> Is this part of the official requirement on ranges? I've been guilty
> of writing ranges whose popFront are no-ops when the range is empty
> (simply because for some ranges, it's a pain to explicitly check for
> this and throw, when the popFront computation doesn't actually assume
> anything about emptiness).
>
Actually, I'm not sure on that one. I would think that calling
front on an empty range should throw. Or at least in a typical
well-behaved range it should, even if it's not specifically stated as
being technically mandatory. But in any case, it was only an example.
>
> > - Iterating via back/popBack yields the same elements as
> > front/popFront, but in reverse order.
>
> Doesn't work on infinite ranges. :) (You *can* have infinite ranges
> with two ends. There's no good reason to do that, of course, because
> they are effectively just two infinite forward ranges stuck together
> at their infinite ends, which is kinda pointless, but in theory, this
> *can* happen.)
>
Naturally, the testing would be different on different types of ranges.
The tester could auto-detect things like "isInfiniteRage" and
"hasLength", and act accordingly.
And of course, if you want to guarantee your range is indeed, for
example, a "hasLength", then you can also just add "static
assert(hasLength!MyRange);" alongside your call to the tester.
More information about the Digitalmars-d
mailing list