Kevin Bealer wrote:
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.
}
You read my mind. I was thinking of something with "copy" in the name.
Andrei