On Sunday, 31 May 2015 at 17:50:41 UTC, Dmitry Olshansky wrote:


2. If we were to reuse algorithms - most algorithms love ForwardRange. And there is a problem implementing it for streams in the _range_ API itself.

Yeah, most streams are seekable like e.g. files or MM-files, so they must be ForwardRanges... And indeed saving position is trivial.

Now look at the signature for ForwardRange:
struct Range{
        ...
        @property Range save();
}

Yeah, you'd gotta duplicate the whole stream to count as ForwardRange. Yicks! Signatures that might work are:

Mark save();
void restore(Mark m);


I think here you confuse typical Range semantics with the semantics of the most prominent but also most akward Range implementation: dynamic arrays. In my opinion the signature of 'save' for ForwardRanges is good. With most ranges the 'mark' of yours is already embedded inside the range type and manipulated with 'popFront' (and 'popBack'). Other range data is most probably stored with indirection so copying it is no harm. As an example there is std.container.SList which is not a range. SList[] returning SList.Range is. It references its SList without owning it and therefore can be copied at will without touching the original SList.

I cannot think of a stream that deserves to be a ForwardRange but is incompatible with this range pattern. Raw file handles cannot be ForwardRanges because multiple aliasing ranges would cause incorrect results. Your proposed signatures wouldn't help either. An inefficient file handle wrapper could be a correct ForwardRange if it seeks some defined position before every read operation. But again this would mean embedding this 'mark' inside the range.

Reply via email to