On 09/05/2019 12:51 PM, berni wrote:

>>     int[int] a;
>>
>>     immutable int b = 17;
>>     a[1] = b;                          // <-- expecting error here

As explained elsewhere, a[1] is a mutable int. That assignment is copying b on top of the element.

>>     const oldPointer = (1 in a);
>>     immutable int c = 10;
>>     a[1] = c;
>>     assert(oldPointer is (1 in a));
>>
>>     Point[int] d;
>>
>>     immutable Point e = Point(17);
>>     d[1] = e;                           // <-- but error is here

That is the equivalent of

  d[1].x = e.x;

It can't work because the left-hand side is immutable. (immutable or const members make objects of those types unassignable.)

>> const or immutable members make structs unassignable.
>
> But why? Here:

Otherwise the immutability guarantees woul be violated.

I understand your questioning the AA design but at the lowest level it's just assignment operation. I understand that it could be "emplacement" on top of the existing element but the guarantees would be violated even then because the 'in' operator returns a pointer. Placing a new object on the same address would make existing pointer-holders unhappy.

> I understand, that I cannot change f[0], because it's allready got a
> default value and that value would be overwritten. But in an aa, that
> member does not exist before putting the Point in there, hence there is
> nothing, that could be overwritten...

Yeah, it's highly likely just assignment on a default-valued object.

>> Whether the members of a type are const or immutable should not be
>> dictated by where the objects of that type will be used. If it makes
>> sense otherwise, sure...
>
> I'm not sure if I understand that right. It's sort of an advice on how
> to decide if one want's to make a member immutable or not, is it?

If it makes for the type to have immutable (or const) members, then fine; with the understanding that objects of that type cannot be assigned or mutated any other way, we can define them like that. What I meant is, because we want to use such a type in an AA and we don't want the element to change should not dictate the type's members. Using in an AA should be yet another usage of the type.

> if immutable were that useless, why would it exist
> at all?

immutable is useful: You can have immutable objects, immutable AAs (different from what we are discussing here), etc.

You can use immutable at a different level: not members but their members can be immutable. For example, a 'string' member would not be immutable itself but its chars would be immutable. There is no problem in having an AA with types having such a member:

struct Person {
  string name;
}

You can assign to Person objects but their names are immutable. If you wanted a Person where the name should never change, then you could make a const(Person), immutable(Person), or provide read-only access to 'name', etc.

> So I would like to understand, what's happening; being able to
> predict, what works and what not. At the moment it's almost always the
> opposite of what I think it should be...

As a general rule, I never make members const or immutable; this is a guideline that I carried over from C++. A recent issue I had with const members in C++ has been silent skipping of move assignment of objects. Unless one uses functional programming style, that's how it should be in D as well. Otherwise, assignment is disabled and AAs don't work as expected because they use assignment under the hood as well.

Ali

Reply via email to