How to correctly handle immutable ranges
Peter Alexander
peter.alexander.au at gmail.com
Mon Dec 31 05:31:43 PST 2012
Here's a few facts:
(assume R is any range type)
1. All immutable(R) cannot be iterated using popFront (obviously).
2. Most immutable(R) cannot be iterated using foreach. The
exception is immutable(T[]), which can.
3. In theory, immutable(R) could be iterated if it had immutable
opIndex and length. However, to return a subrange you also need
immutable opSlice. foreach does not use this.
4. When passed into a function, top-level immutable is removed
for arrays and pointers, but no other type (can someone tell me
why?).
Now, suppose I want to write a simple function that looks for a
subrange in a range of ranges. Here's what I would probably write
(ignoring custom predicates, optimisations etc.)
RoR findSubrange(RoR, R)(RoR ror, R r)
if (isInputRange!RoR &&
isInputRange!(ElementType!RoR) &&
isInputRange!R)
{
for (; !ror.empty; ror.popFront())
if (equal(ror.front, r))
break;
return ror;
}
This function has a few problems:
A. If you pass an immutable array for ror, the top-level
immutable will be stripped, giving you a mutable ror. Great.
However, only the top level immutable is stripped. If the
subranges are immutable then they will stay immutable and the
second line of the template constraint will fail.
B. If you change the second line to
isInputRange!(Unqual!(ElementType!RoR)) then you will correctly
accept immutable arrays, but you also end up accepting ranges of
other immutable ranges, which in general are not iterable, so the
call to equal will fail.
C. If you change the second line to isIterable!(ElementType!RoR)
then it will fail when the element type has opApply. Also, equal
only requires isInputRange, so whether or not it fails depends on
whether equal uses popFront or not (it doesn't for arrays, but it
could...)
D. If RoR is any sort of wrapper around arrays (e.g.
map!"a"(ror)) then it will fail because top level immutable is
not stripped. In theory, you could iterate the map over array by
using opIndex, length, and return a slice, but that would require
a lot of duplication of code.
My questions are:
1. First, why is top-level immutable stripped for arrays and
pointers but not other types?
2. How should you handle the special case of ranges of immutable
arrays in a consistent manner?
3. How should you handle the alternate iteration method with
opIndex/length/opSlice?
Cheers,
Peter
More information about the Digitalmars-d
mailing list