On Monday, 31 December 2012 at 14:24:53 UTC, monarch_dodra wrote:
The same can't be said about ranges: a "immutable(Range!T)"
might not safely copyable as a "Range!(immutable(T))"
Hmm, are you sure? Can you give an example? Surely if Range is a
struct and everything is copied then it can all change from
mutable to immutable (using a postblit where necessary).
Maybe we just need copy constructors for this to work around the
const issue with postblit.
3. No idea.
There is one way you could work around it in a generic manner,
but involves a bit of boilerplate:
auto iterable(R)(R r)
{
struct Iterable
{
this(R range) { _range = range; }
static if (isInputRange!R)
{
alias _range this;
alias _range result;
}
else static if (isRandomAccess!R && hasLength!R && hasSlicing!R)
{
@property auto front() { return _range[_index]; }
@property bool empty() const { return _index == _range.length;
}
void popFront() { ++_index; }
@property auto save() { return this; }
@property R result() { return _range[_index..$]; }
private size_t _index = 0;
}
private R _range;
}
return Iterable(r);
}
You just have to use iterable everywhere instead of the range,
and then use .result to get back to the original range type. e.g.
RoR findSubrange(RoR, R)(RoR ror, R r)
{
auto _ror = iterable(ror);
auto _r = iterable(r);
for (; !_ror.empty; _ror.popFront())
if (equal(iterable(_ror.front), _r))
break;
return _ror.result;
}
Warning: code is totally untested, but should give the gist of
the idea.
That said, some might question the entire concept of an
"immutable range". a "range of immutables" makes sense, the
other way around: less so (IMO).
I kind of agree, but unfortunately immutable arrays are iterable,
and arrays are the most common range, so we really need to
support them.