stream == range ? [Sliding window]

Dmitry Olshansky via Digitalmars-d digitalmars-d at puremagic.com
Sun May 31 14:50:28 PDT 2015


On 01-Jun-2015 00:18, Mafi wrote:
> 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.

I'm quite certain I'm talking of something beyond dynamic arrays - 
buffered I/O much like D's std.stdio File wrapper of C's FILE I/O.

> 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.

Ranges were designed with algorithms and containers in mind. Current I/O 
ranges were fitted in with a bit of strain and overhead.

> 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.

The idea of reading raw file handles 1 byte at a time just to fit 
InputRange interface is hilarious. What is an algorithm that *anyone* in 
the right state of mind would want to run on raw file handle using such 
interface?
Also it makes sense to accommodate a better set of primitives for raw 
I/O, including support for scatter-gather read/write. And we wouldn't 
have to constraining ourselves with stupid things like bool empty() - 
that no one knows for sure until we read that file, pipe, socket...

On the other hand saving the state of a buffered stream is doable but 
using the same type is unfortunate restriction.

 >
> 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.

I'm talking about buffered stuff obviously.
Also e.g. in memory-mapped file is trivial to save a position, and it 
wouldn't require mapping all at once.

Speaking of InputRange as unbuffered stream, I'll refine my reply to 
Andrei with more facts.

That range jacket simply doesn't fit:
	- it requires buffering 1 element (front)
	- requires primitives that are impossible to decently  implement (e.g. 
empty)
	- convincingly suggest primitives that are anti-pattern in I/O: a 
syscall per 1-element read? (at best)

Unbuffered I/O doesn't work like 3 separate things "peek, advance and 
test for empty" troika. Otherwise I'm all for design by introspection 
realization, it's just that I/O needs its own foundations.

-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list