December 10, 2012
On 12/10/12 1:55 PM, Jacob Carlborg wrote:
> On 2012-12-10 17:06, Dan wrote:
>
>> I think so. Here is a claim I think is true: gdup must do full deep copy
>> to be safe and guarantee the transitive const/immutable. If it is
>> implemented such that there are no casts, then the compiler does its job
>> and ensures everything is good. If there are casts they need to be
>> deemed safe - I have one cast to work around issues in associative array
>> iteration.
>
> I'm pretty sure it can't be done.

Just like Dan I thought it can be done but actually ownership is impossible to establish in general. Consider:

class List(T) {
    List next;
    T payload;
    ...
}

versus

class Window {
    Window parent;
    ...
}

It's pretty obvious from the name that duplicating a List would entail duplicating its tail, whereas duplicating a Window would entail just copying the reference to the same parent. However, at the type level there's no distinction between the two members.

Now, user-defined attributes could change the playfield radically here. Consider we define things like @owned and @foreign that would inform the gdup or deepdup function appropriately:

class List(T) {
    @owned List next;
    T payload;
    ...
}

versus

class Window {
    @foreign Window parent;
    ...
}

Now a generic deep duplication function has enough information to duplicate things appropriately.


Andrei
December 10, 2012
On 12/10/12 2:07 PM, Dan wrote:
> On Monday, 10 December 2012 at 18:55:09 UTC, Jacob Carlborg wrote:
>
>> I'm pretty sure it can't be done. For classes one need to bypass the
>> constructor. The constructor is the only place where you can
>> initialize const/immutable fields. For class instance one would need
>> to cast it to a ubyte pointer (or similar) and then set the
>> const/immutable fields that way.
>>
>> I think it can be done safely, but not something the compiler can
>> guarantee.
>
> Only talking about structs here. classes were listed under issues not
> covered.
>
> Thanks
> Dan

There will be the same problems with structs containing pointers.

Andrei
December 10, 2012
On Monday, 10 December 2012 at 19:46:18 UTC, Andrei Alexandrescu wrote:
> On 12/10/12 1:55 PM, Jacob Carlborg wrote:
>> On 2012-12-10 17:06, Dan wrote:
>>
>>> I think so. Here is a claim I think is true: gdup must do full deep copy
>>> to be safe and guarantee the transitive const/immutable. If it is
>>> implemented such that there are no casts, then the compiler does its job
>>> and ensures everything is good. If there are casts they need to be
>>> deemed safe - I have one cast to work around issues in associative array
>>> iteration.
>>
>> I'm pretty sure it can't be done.
>
> Just like Dan I thought it can be done but actually ownership is impossible to establish in general. Consider:
>
> class List(T) {
>     List next;
>     T payload;
>     ...
> }
>
> versus
>
> class Window {
>     Window parent;
>     ...
> }
>
> It's pretty obvious from the name that duplicating a List would entail duplicating its tail, whereas duplicating a Window would entail just copying the reference to the same parent. However, at the type level there's no distinction between the two members.
>

Unless the tail is immutable, but in general yes.

> Now, user-defined attributes could change the playfield radically here. Consider we define things like @owned and @foreign that would inform the gdup or deepdup function appropriately:
>
> class List(T) {
>     @owned List next;
>     T payload;
>     ...
> }
>
> versus
>
> class Window {
>     @foreign Window parent;
>     ...
> }
>
> Now a generic deep duplication function has enough information to duplicate things appropriately.
>

That is indeed a perfect use case for attributes.
December 10, 2012
On 2012-12-10 20:46, Andrei Alexandrescu wrote:

> Just like Dan I thought it can be done but actually ownership is
> impossible to establish in general. Consider:
>
> class List(T) {
>      List next;
>      T payload;
>      ...
> }
>
> versus
>
> class Window {
>      Window parent;
>      ...
> }
>
> It's pretty obvious from the name that duplicating a List would entail
> duplicating its tail, whereas duplicating a Window would entail just
> copying the reference to the same parent. However, at the type level
> there's no distinction between the two members.

I'm not sure, why wouldn't you want to copy the parent window as well?

-- 
/Jacob Carlborg
December 10, 2012
On Monday, 10 December 2012 at 19:40:52 UTC, Jacob Carlborg wrote:
> On 2012-12-10 20:37, Jacob Carlborg wrote:
>
>> You might have the same problem with structs. That is, if it's possible
>> to have const/immutable files which are not initialized in the declaration.
>
> That should have been "fields".

You are correct. const or immutable fields won't work. But then, if you had a field that was const or immutable you might as well make it static. Any problems with gdup in that case would be the same you would see if you wanted to implement your own.
December 10, 2012
On 2012-12-10 20:55, Dan wrote:

> You are correct. const or immutable fields won't work. But then, if you
> had a field that was const or immutable you might as well make it
> static. Any problems with gdup in that case would be the same you would
> see if you wanted to implement your own.

As I wrote in a previous post, it's possible to implement. I've done it in my serialization library.

-- 
/Jacob Carlborg
December 10, 2012
On 12/10/12 2:54 PM, Jacob Carlborg wrote:
> On 2012-12-10 20:46, Andrei Alexandrescu wrote:
>
>> Just like Dan I thought it can be done but actually ownership is
>> impossible to establish in general. Consider:
>>
>> class List(T) {
>> List next;
>> T payload;
>> ...
>> }
>>
>> versus
>>
>> class Window {
>> Window parent;
>> ...
>> }
>>
>> It's pretty obvious from the name that duplicating a List would entail
>> duplicating its tail, whereas duplicating a Window would entail just
>> copying the reference to the same parent. However, at the type level
>> there's no distinction between the two members.
>
> I'm not sure, why wouldn't you want to copy the parent window as well?

You want to create a new window with the same parent. At the top level there's one desktop window, and probably having two would be odd.

Andrei

December 10, 2012
On Monday, 10 December 2012 at 20:10:25 UTC, Andrei Alexandrescu wrote:

> You want to create a new window with the same parent. At the top level there's one desktop window, and probably having two would be odd.
>

Ok - so I'm only talking about structs.

What you say is what you want here and it makes sense. But that is not what I'm proposing. I'm just talking deep copy of structs that is always deep copy - period (bearophile called it transitive copy). By design that means there is no aliasing at all. So in this case the parent window would be deep copied. This can be done without any change to the struct (cycles when pointers are used are one design issue that would need to be addressed). This is also why gdup can be used to copy any immutable(T) into T (assuming is(T==struct)) and get around the "how do I copy const/immutable instances" we see so often.

Below illustrates what would happen and you would not want it for Window parent/child relationships - but you see the consistency. For what you describe you want reference semantics and gdup is not needed.

Given this - I think the original claim still holds.
    I claim that gidup or igdup or whatever
    can just be:

    @property auto gidup(T)(const ref T t) {
      immutable(T) result = cast(immutable)(t.gdup);
      return result;
    }

I am not saying you can or should gdup any struct instance willy nilly, just that the cast to immutable here is safe because all fields are deep copied recursively.


------------------- output -------
Window("c1", 5, 5, 7FFF5BF3F4F0)
Window("c1", 5, 5, 7FAC74004FE0)
-------------------
import std.stdio;
import opmix.mix;

struct Window {
  string name;
  int x, y;
  Window *parent;
}

void main() {
  auto window = Window("root", 1, 1);
  auto child = Window("c1", 5, 5, &window);
  auto c2 = child.gdup;
  writeln(child);
  writeln(c2);
}
December 10, 2012
On 2012-12-10 21:10, Andrei Alexandrescu wrote:

> You want to create a new window with the same parent. At the top level
> there's one desktop window, and probably having two would be odd.

There are many applications that support several top level windows. These are mostly document based.

-- 
/Jacob Carlborg
December 10, 2012
On 12/10/12 4:20 PM, Jacob Carlborg wrote:
> On 2012-12-10 21:10, Andrei Alexandrescu wrote:
>
>> You want to create a new window with the same parent. At the top level
>> there's one desktop window, and probably having two would be odd.
>
> There are many applications that support several top level windows.
> These are mostly document based.

Are we really up for continuing to debate this?

Andrei