Re: What is special about an immutable array of class objects, and why can I not .dup ?

2018-05-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/28/18 9:51 AM, James Blachly wrote:

Why are the class objects special in this case, and why does 
`immutable(C)[]` not help?   I believed that this defined a dynamic 
array `c` which was itself mutable, the elements of which were immutable.


To build on what others have said, the key thing you are missing is that 
every instance of C is a *reference*. So you essentially have an array 
of pointers.


If you dup the array, you are not duplicating the class instances, each 
element of the array still points at the same instances! So naturally, 
you can't have both a mutable and immutable reference to the same instance.


This is easily demonstrated:

auto c = [new C(), new C()];
c[0].x = 5;
auto c2 = c.dup;
c2[0].x = 6;
writeln(c[0].x); // 6

Contrast that with the struct and int arrays, where the *entire 
contents* are copied.


Hope that helps.

-Steve


Re: What is special about an immutable array of class objects, and why can I not .dup ?

2018-05-28 Thread bauss via Digitalmars-d-learn

On Monday, 28 May 2018 at 13:51:49 UTC, James Blachly wrote:

Consider the below:

```
class C
{
int x;
}

struct S
{
int x;
}


void main()
{
immutable C[] c = [ new C(), new C()];
immutable S[] s = [ S(), S() ];
immutable int[] i = [ 1, 2 ];

auto x = c.dup;
auto y = s.dup;
auto z = i.dup;

}
```

This fails to compile with a `.dup` template matching error at 
line `auto x = c.dup;`. However, calling `.idup` works just 
fine. The immutable struct array and int array of course `.dup` 
just fine.


I would have guessed that changing the definition of `C[]` to 
`immutable(C)[]` would have also helped, but it did not.


Why are the class objects special in this case, and why does 
`immutable(C)[]` not help?   I believed that this defined a 
dynamic array `c` which was itself mutable, the elements of 
which were immutable.


Thanks for insights.


I'm going to make a wild guess that .dup is a shallow copy and if 
the class has any members that are reference types only 
references to them are copied.


Which means that by creating a mutable duplicate of the class you 
essentially have a mutable reference to said member.


Even though in your example that isn't the case, then that's the 
only reason I can think of the restriction making sense.





Re: What is special about an immutable array of class objects, and why can I not .dup ?

2018-05-28 Thread Jonathan M Davis via Digitalmars-d-learn
On Monday, May 28, 2018 13:51:49 James Blachly via Digitalmars-d-learn 
wrote:
> Consider the below:
>
> ```
> class C
> {
>  int x;
> }
>
> struct S
> {
>  int x;
> }
>
>
> void main()
> {
>   immutable C[] c = [ new C(), new C()];
>   immutable S[] s = [ S(), S() ];
>  immutable int[] i = [ 1, 2 ];
>
>  auto x = c.dup;
>  auto y = s.dup;
>  auto z = i.dup;
>
> }
> ```
>
> This fails to compile with a `.dup` template matching error at
> line `auto x = c.dup;`. However, calling `.idup` works just fine.
> The immutable struct array and int array of course `.dup` just
> fine.
>
> I would have guessed that changing the definition of `C[]` to
> `immutable(C)[]` would have also helped, but it did not.
>
> Why are the class objects special in this case, and why does
> `immutable(C)[]` not help?   I believed that this defined a
> dynamic array `c` which was itself mutable, the elements of which
> were immutable.
>
> Thanks for insights.

dup makes the entire thing mutable, and the compiler can't safely convert
immutable class references to mutable ones. And when you think about it, the
immutability of the array itself really isn't the key thing here anyway. All
you have to do to get a mutable one is to slice it - slicing gives you a
tail-const/tail-immutable dynamic array pointing to the same data. So,
ultimately, what you're doing with dup vs idup is deciding what the
mutability of the elements is. dup makes them mutable, and idup makes them
immutable. In the case of primitive types or structs which don't have
postblit constructors, that's usually trivial, but it doesn't work with
class references. For them, you're stuck with the same level of mutablity,
because there is no easy conversion for them between mutable and immmutable.

- Jonathan M Davis



What is special about an immutable array of class objects, and why can I not .dup ?

2018-05-28 Thread James Blachly via Digitalmars-d-learn

Consider the below:

```
class C
{
int x;
}

struct S
{
int x;
}


void main()
{
immutable C[] c = [ new C(), new C()];
immutable S[] s = [ S(), S() ];
immutable int[] i = [ 1, 2 ];

auto x = c.dup;
auto y = s.dup;
auto z = i.dup;

}
```

This fails to compile with a `.dup` template matching error at 
line `auto x = c.dup;`. However, calling `.idup` works just fine. 
The immutable struct array and int array of course `.dup` just 
fine.


I would have guessed that changing the definition of `C[]` to 
`immutable(C)[]` would have also helped, but it did not.


Why are the class objects special in this case, and why does 
`immutable(C)[]` not help?   I believed that this defined a 
dynamic array `c` which was itself mutable, the elements of which 
were immutable.


Thanks for insights.