Andrei Alexandrescu:

Would joiner help?

I don't know. I think the point of those segmented ranges is to not hide their segmented nature (as joiner does).

- - - - - - - - - - - - - -

This paper shows a variant of the stream fusion, applied on chunked arrays that represent strings:

"Rewriting Haskell Strings" (2007) by Duncan Coutts, Don Stewart, Roman Leshchinskiy:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.90.3166


In D it's easy to create a range that segments a given lazy range into a lazy iterable of arrays:


import std.range: ElementType;
import std.array: empty, front, popFront;

struct Segmenter(size_t chunkLength, Range) {
    alias ElementType!Range elementT;
    private elementT[chunkLength] chunk;
    private Range r;
    private size_t len;

    this(Range rin) {
        this.r = rin;
        popFront();
    }

    @property bool empty() const {
        return len == 0 && r.empty;
    }

    @property elementT[] front() pure nothrow {
        return chunk[0 .. len];
    }

    void popFront() {
        len = 0;
        while (len < chunkLength && !r.empty) {
            chunk[len] = r.front;
            len++;
            r.popFront();
        }
    }
}


But Phobos ranges don't manage segments automatically (so you can't just apply a normal map on a Segmenter, because this map will work on the chunks), and there aren't the optimizations described in that paper. On the other hand some range methods become inlined, because D ranges are quite different from Haskell lazy lists, so maybe some of those optimizations are not needed.

Bye,
bearophile

Reply via email to