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