When does take modify the underlying iterator?
cy via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Aug 16 14:01:14 PDT 2016
InputRanges that are not ForwardRanges seem to lack a possibly
crucial operation. I want to start with an arbitrary range, take
1 from it, then process the rest. But there doesn't seem to be
any way to do that, because there's no way to tell whether "take"
will advance the range, or whether it will leave the range as-is.
When you know a range implements front, empty, and popFront, and
you take from that range, there seems to be a secret requirement
that the iterator supports save() via copy constructor. And if it
doesn't... your program just breaks silently when you drop
elements that haven't been processed yet.
Is there some way around that, that I'm not aware of?
struct CertainlyNotAForwardRange(A) {
static int i = 0;
A a;
auto front() {
return a[i];
}
auto empty() {
return i == a.length;
}
auto popFront() {
++i;
}
}
struct SecretlyForwardRange(A) {
A a;
int i = 0;
auto front() {
return a[i];
}
auto empty() {
return i == a.length;
}
auto popFront() {
++i;
}
}
auto failhard(T)(T iter) {
import std.stdio;
import std.range: take, drop;
import std.array: array;
writeln("We have some range:");
writeln(typeid(T));
writeln("We take 1 from it...");
writeln(iter.take(1));
writeln("The rest of the range has:");
writeln(iter.drop(1).array);
writeln("");
}
void main() {
auto arr = [0, 1, 2, 3];
failhard(arr);
failhard(SecretlyForwardRange!(typeof(arr))(arr));
failhard(CertainlyNotAForwardRange!(typeof(arr))(arr));
}
More information about the Digitalmars-d-learn
mailing list