View mode: basic / threaded / horizontal-split · Log in · Help
December 10, 2012
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
Re: proposal for general dup function
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
1 2 3
Top | Discussion index | About this forum | D home