Jump to page: 1 2 3
Thread overview
proposal for general dup function
Dec 09, 2012
Dan
Dec 09, 2012
Jacob Carlborg
Dec 10, 2012
Dan
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
Dan
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
Dan
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
Dan
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
deadalnix
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
Dan
Dec 10, 2012
Jacob Carlborg
Dec 10, 2012
Dan
Dec 11, 2012
Jacob Carlborg
December 09, 2012
Phobos can and should have a general dup function, capable of duping (i.e. recursive deep copy) structs without requiring any effort from struct developers. This can be done to cover the vast majority of object copy issues for structs and would have these benefits:

- no need to write (and potentially mess up) a dup function for your own structs
- ability to dup structs that others have written for which you don't have direct read access to all the fields
- as your structs grow less chance of bugs (the general dup would recognize and incorporate new fields)
- it addresses the inability to copy const and immutable reference structs (which Walter and Andrei may be looking to address with copy constructor feature)
- it would add more formality to the dup convention

Issues not covered:

- custom memory management by struct, some structs want to do low level stuff themselves. This is ok, though, as the struct developer can write his own dup and that will be honored by the general dup when composition requires it
- some resources are based on handles that can lead to indirection. For example, deep copy of file handles could cause unintended sharing. In these cases the back door is for the developer to write a custom dup or disable dup.
- classes not covered. Maybe the approach could be extended to support classes - but it is much more complicated.

Sample implementation:

I've written one called gdup just to distinguish it from dup. It is a function and a property, so the usage should feel natural. An example usage is shown below. Implementation and tests are located at:

https://github.com/patefacio/d-help/blob/master/d-help/opmix/mix.d
https://github.com/patefacio/d-help/blob/master/d-help/opmix/d_test/gdup_suite.d

A pdf writeup exists in section "dup and Global Dup" at:
https://github.com/patefacio/d-help/blob/master/doc/canonical.pdf?raw=true

The specific functions related to gdup are:

@property auto gdup(T)(const ref T t)
void gdup(T1, T2)(ref T1 t1, const ref T2 t2)
ref T opDupPreferred(T, F)(ref T target, const ref F src)

Some sample questions to the news group where this feature in the standard library would solve a user problem:

http://forum.dlang.org/thread/mailman.1946.1352987649.5162.digitalmars-d-learn@puremagic.com?page=3
http://forum.dlang.org/thread/pzuparprsetydynbcuce@forum.dlang.org
http://forum.dlang.org/thread/urvdcpflzajhpackmxyz@forum.dlang.org


Thanks
Dan

  static struct A {
    char[] c;
  }
  static struct B {
    A a;
  }
  static struct C {
    B b;
  }
  void main() {
    const(C) c = C(B(A(['a'])));
    C c2 = c.gdup;
  }
December 09, 2012
On 2012-12-09 15:45, Dan wrote:
> Phobos can and should have a general dup function, capable of duping
> (i.e. recursive deep copy) structs without requiring any effort from
> struct developers.

[snip]

I think much of this functionality could be shared with serialization. A few questions and comments.

* Are array slices properly handled
* I think there need to be a way to explicitly say that a given field and a whole struct shouldn't be duped
* All the public strings used for mixins should be templates

Orange serialization library, supports classes as well:

https://github.com/jacob-carlborg/orange

-- 
/Jacob Carlborg
December 10, 2012
On Sunday, 9 December 2012 at 16:26:12 UTC, Jacob Carlborg wrote:
> On 2012-12-09 15:45, Dan wrote:
>> Phobos can and should have a general dup function, capable of duping
>> (i.e. recursive deep copy) structs without requiring any effort from
>> struct developers.
>
> [snip]
>
> I think much of this functionality could be shared with serialization. A few questions and comments.
>

I am talking about a much smaller scope (just a few of functions - 200 lines of code tops) - but there are similarities.

> * Are array slices properly handled

Both array slices and associative arrays are properly handled. Let me know if you find otherwise.

> * I think there need to be a way to explicitly say that a given field and a whole struct shouldn't be duped

I definitely see need for that in serialization. Not sure about a generalized dup function, though. I have a similar function for deeply comparing instances and I think this should always hold:

assert(typesDeepEqual(t, t.gdup))

If you skipped fields it would not.

> * All the public strings used for mixins should be templates
>

The mixins in the code are for higher-up functionality, some of it on top of the dup. There is no need for mixin for a general dup. The mixin(PostBlit) is there if you want to provide a dup for your struct so assignments in generic code gets the deep copy semantics with opAssign and copy construction. However, if template mixins are preferred to string mixins I suppose that is a good idea for that code and I'll check it out.

I have refactored the dup into its own module, so there is no need for mixin:
https://github.com/patefacio/d-help/blob/master/d-help/opmix/dup.d

> Orange serialization library, supports classes as well:
>
> https://github.com/jacob-carlborg/orange
December 10, 2012
On 2012-12-10 13:56, Dan wrote:

> However, if template mixins are preferred to
> string mixins I suppose that is a good idea for that code and I'll check
> it out.

Yes, templates are always preferred. One should try to avoid putting code in string literals as much as possible.

-- 
/Jacob Carlborg
December 10, 2012
On 12/09/2012 03:45 PM, Dan wrote:
> Phobos can and should have a general dup function, capable of duping (i.e.
> recursive deep copy) structs without requiring any effort from struct
> developers. This can be done to cover the vast majority of object copy issues
> for structs

We already had some discussion about your gdup on d-learn, but just for clarity -- it's possible to do a gidup as well as gdup, correct?

December 10, 2012
On Monday, 10 December 2012 at 15:36:44 UTC, Joseph Rushton Wakeling wrote:
> On 12/09/2012 03:45 PM, Dan wrote:
>> Phobos can and should have a general dup function, capable of duping (i.e.
>> recursive deep copy) structs without requiring any effort from struct
>> developers. This can be done to cover the vast majority of object copy issues
>> for structs
>
> We already had some discussion about your gdup on d-learn, but just for clarity -- it's possible to do a gidup as well as gdup, correct?

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. Assuming that is fine - 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;
}

    auto another = c.gidup;
    pragma(msg, typeof(another));
    assertNotEquals(another.b.a.c.ptr, c.b.a.c.ptr);
    assert(0==typesDeepCmp(another,c));

That is, since gdup does a full deep copy, casting the result to immutable is fine as there is no aliasing.

Thanks,
Dan
December 10, 2012
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. 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.

-- 
/Jacob Carlborg
December 10, 2012
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
December 10, 2012
On 2012-12-10 20:07, Dan wrote:

> Only talking about structs here. classes were listed under issues not
> covered.

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.

-- 
/Jacob Carlborg
December 10, 2012
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".

-- 
/Jacob Carlborg
« First   ‹ Prev
1 2 3