On Sunday, 22 September 2013 at 20:17:03 UTC, Jonathan M Davis wrote:
If you have

struct S
{
    immutable int[] arr;
}

then arr can never be assigned to, so a variable of type S can never be
assigned to. But if you have

Yes - it (arr) can never be assigned to. That is the idea. It has already been assigned to when the data was read in, prior to construction of S. arr is initialized in the ctor of S.


struct S
{
    immutable(int)[] arr;
}

then arr can be reassigned as much as you'd like, so S can be assigned to.

I don't imagine wanting that in this case. I want to ensure the array passed at construction in is the same array being used in read-only fashion throughout the lifecycle of S. That is my intention behind using immutable. I'm saying I'll not change it and no one else can, other wise functions of S that might have made assumptions about arr could be invalidated.

In
both cases, the elements of the array are immutable, so it can freely be a slice of another array and not care or affect that other array, but the array variable itself - which only exists local to the struct - is not restricted in being assigned to. So, you get the immutability of the data without restricting the struct. All making arr itself immutable does (rather than
tail-immutable) is make it so that you can't reassign arr,

It also keeps the contents of arr from growing and surprising S . You could try to prevent with private, but still if it is a large module why not have the commitment not to change the contents (including the length), especially if it is important that you know the data is not changing.

which can be useful
sometimes, but in the case of a struct, it makes it so that the whole struct can't be reassigned, so it's pretty much never a good idea IMHO to have a
struct with const or immutable members -

Why that conclusion? That is, why should reassignment of S take priority over stable data used by S? For example, take something like a BalanceSheetForecaster which takes a BalanceSheet as input in its ctor. Isn't it important that the numerous queries on and forecasts by the BalanceSheetForecaster be on *exactly* the same data?

but having them be tail-const or
tail-immutable still makes it so that what they refer to gets all of the
benefits of const or immutable without restricting the struct.


I appreciate the explanation and think I understand the benefit of tail-const better. You would not easily be able to store modifiable collections of BalanceSheetForecasters, unless you did it with pointers. But the focus of the discussion seems to be on immutable(T)[] which is my fault for choosing the first and easiest type of aliasing I could in my example. I think the slice is really a special case when it comes to aliasing. With immutable(T)[] you have the benefit of not having to worry about aliasing because of the way it is implemented - the contiguous nature and copy on write semantics. But this is not the general case is it? For example, do the same arguments hold for associative arrays?

struct S {
  immutable string[string] aarr;
}

Doesn't using immutable there present the same problem as with the slice? S is no longer assignable. But who would recommend not using immutable in this case if you want aarr to be stable. If you do not use immutable then who knows when your array will grow without your expecting it? At least with the slice your memory safety is in the control of your module if you make it private. But with associative array it would depend entirely on client code providing the data still having a handle on it.

Reply via email to