How to correctly handle immutable ranges
monarch_dodra
monarchdodra at gmail.com
Mon Dec 31 08:29:25 PST 2012
On Monday, 31 December 2012 at 14:58:03 UTC, Peter Alexander
wrote:
> 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?
Yes, any (well, most) reference type range will fail the
conversion. For example:
import std.array;
//---
struct ShallowRange(T)
{
T[]* payload;
T front() const {return (*payload).front;}
void popFront(){(*payload).popFront;}
bool empty() const {return (*payload).empty;}
}
ShallowRange!T shallowRange(T)(ref T[] data)
{
return ShallowRange!T(&data);
}
immutable(ShallowRange!T) immutableShallowRange(T)(ref
immutable(T[]) data)
{
return cast(immutable(ShallowRange!T))
ShallowRange!T(cast(T[]*)&data);
}
void main()
{
immutable(int)[] slice = [1, 2, 3];
immutable(int[]) iSlice = [1, 2, 3];
ShallowRange!(immutable(int)) range = shallowRange(slice);
immutable(ShallowRange!int) iRange =
immutableShallowRange(iSlice);
}
//---
Here, I have a slice of immutables (slice) and an immutable slice
(iSlice), which I place in a range of immutables, and an
immutable range (respectivelly).
If you cast my immutable range to a range of immutables, and then
attempt to iterate over it, you are going to modify my immutable
iSlice...
> Surely if Range is a struct...
I'm not well versed in how classes and immutability work
(especially when discussing the immutability of the class object
itself, vs the class + class reference).
But yeah, keep in mind a range can be implemented as a class.
> ... 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.
I think this is a language wide issue (well, concept). A range
really is no different from any other object, and you really
can't know what will happen when you copy them.
As a general rule, even via CC, you can't assume the result of
copying a "immutable(S!T)" (or "immutable(S!(immutable(T))") will
be a "S!(immutable(T)".
--------
But back to the original problem, I just think one shouldn't be
able to call a const object a range. A "Range" is mutable by
nature. Any attempt to pass one to an algorithm should fail (IMO).
I've yet to see anybody try to manipulate const ranges anyways
(which probably isn't a coincidence), though someone one prove me
wrong/disagree.
We just have a really special case regarding const slices. Even
then, the only reason you can "iterate them" is because the
compiler is implicitly copying a mutable slice behind the scenes.
The const slice itself, technically, really isn't iterable
(AFAIK)...
I think the slices' behavior twists our view of what to expect
from the rest of our ranges.
More information about the Digitalmars-d
mailing list