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.

Reply via email to