Andrei Alexandrescu wrote: > Daniel Keep wrote: >> ... > > So essentially we're looking at a symbolic approach - a resumable range > would need to advertise that. I've used that for isSorted too, and it > works pretty well. > > The remaining question is one of defaults - are most ranges resumable or > not? I.e., should a range advertise explicitly when it's resumable or > when it's *not* resumable? I think the safe approach is to go as you > say: a range ain't resumable unless it explicitly claims to. So if you > forget stuff, the compiler will remind you. > > I'd love to hear more opinions on the topic. > > > Andrei
Actually, I stuffed up the test; I wanted the default to be resumable. :P That'll teach me to not double-check my logic. A quick truth table later, and the correct test is this: > template isResumableRange(R) > { > enum bool isResumableRange = isInputRange!(R) > && (!is(typeof(R.isResumableRange)) > || (is(typeof(R.isResumableRange)) && R.isResumableRange)) > && is(typeof( > { > R r1; > R r2 = r1; > }())); > } ... I think. :P Actually, I've been thinking and I realised that in 95% of cases, you can assume a range is resumable if it has no references. If it has no references, the only way the range can be non-resumable is if the advance member uses the range's state as an argument to some global method. An example might be a Range that statically accesses Stdout instead of taking it as an argument. It's a real shame the range interface doesn't support this: > struct R > { > ... > pure R advance(); > } If it did, we could prove a range was resumable if advance was pure and R has no mutable or const references. Honestly, I think the safest option is to *require* resuming to be explicitly stated by the programmer. It'd be nice if we could automatically account for some cases, but I can't think of any you couldn't escape from. Maybe we should default to non-resumable for now, then re-visit the issue when we have an idea of how people are using ranges. -- Daniel