algorithms that take ranges by reference

Kevin Bealer kevinbealer at gmail.com
Wed Dec 30 15:22:16 PST 2009


Andrei Alexandrescu Wrote:

> The grand STL tradition is to _always_ take iterators by value. If 
> iterators are computed, they are returned by the algorithm.
> 
> My initial approach to defining std.algorithm was to continue that 
> tradition for ranges: ranges are values. No algorithm currently takes a 
> range by reference. There are a couple of simple functions that 
> emphatically do take ref, namely popFrontN and popBackN in std.range.
> 
> It is becoming, however, increasingly clear that there are algorithms 
> that could and should manipulate ranges by reference. They might take 
> and return values, but it's just too messy to do so. (Cue music for the 
> "improve built-in tuples choir.)
> 
> A concrete case is text processing. Many contemporary libraries use 
> index-based processing, but that's difficult when handling multibyte 
> characters. To address that, bidirectional ranges are one correct way to 
> go. Phobos defines a ByCodeUnit range that spans a string correctly, one 
> dchar at a time. With that, you can write:
> 
...
> Andrei

I would vote yes -- I've used this technique (with my own character slice classes in C++) and they are a great idiom to work with.

I think ranges (and slices) have some of the properties from each of pointers, containers, and streams.  A stream is always a by-ref kind of thing unless you are in a language that needs monads etc.

Let me suggest one more function I've found very useful:

bool readUntil(R1, R2, R3)(ref R1 input, R2 delim, ref R3 result)
{
  // Like findSkip, but returning intervening text.
}

Then you can write something like:

bool consumeQuotedString(R1,R2)(ref R1 text, ref R2 quoted)
{
    if (skip(text, "'")) {
        if (! readUntil(text, "'", quoted)) {
            /*error*/
        }
        return true;
    }
    return found;
}

Kevin




More information about the Digitalmars-d mailing list