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