www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Copy a struct and its context

reply Yuxuan Shui <yshuiv7 gmail.com> writes:
I recently noticed nested struct capture its context by reference 
(which, BTW, is not mentioned at all here: 
https://dlang.org/spec/struct.html#nested). And bliting a struct 
obviously doesn't do a deep copy of its context.

So my question is, is there a way to deep copy the context of a 
struct?
Sep 10 2016
next sibling parent Rene Zwanenburg <renezwanenburg gmail.com> writes:
On Sunday, 11 September 2016 at 05:44:13 UTC, Yuxuan Shui wrote:
 I recently noticed nested struct capture its context by 
 reference (which, BTW, is not mentioned at all here: 
 https://dlang.org/spec/struct.html#nested). And bliting a 
 struct obviously doesn't do a deep copy of its context.

 So my question is, is there a way to deep copy the context of a 
 struct?
I've tried a few things, but I don't think you can. The root issue is that the context pointer is void*, so you can't do meaningful reflection on it.
Sep 11 2016
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 09/10/2016 10:44 PM, Yuxuan Shui wrote:
 I recently noticed nested struct capture its context by reference
 (which, BTW, is not mentioned at all here:
 https://dlang.org/spec/struct.html#nested). And bliting a struct
 obviously doesn't do a deep copy of its context.

 So my question is, is there a way to deep copy the context of a struct?
Can you show a small example? This seems to work: auto foo(int i) { struct S { int foo() { return i; } } return S(); } void main() { auto s = foo(42); auto s_copy = s; assert(s.foo() == 42); assert(s_copy.foo() == 42); } Ali
Sep 12 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/12/16 4:11 PM, Ali Çehreli wrote:
 On 09/10/2016 10:44 PM, Yuxuan Shui wrote:
 I recently noticed nested struct capture its context by reference
 (which, BTW, is not mentioned at all here:
 https://dlang.org/spec/struct.html#nested).
" It has access to the context of its enclosing scope (via an added hidden field)." It needs to be a reference. Otherwise, you store the entire stack frame in the struct? That wouldn't be a "field". It also has write access to the context: void foo() { int i; struct S { void changeI(int newVal) { i = newVal; } } S s; s.changeI(10); assert(i == 10); } The documentation could be clearer.
 And bliting a struct
 obviously doesn't do a deep copy of its context.

 So my question is, is there a way to deep copy the context of a struct?
Can you show a small example? This seems to work: auto foo(int i) { struct S { int foo() { return i; } } return S(); } void main() { auto s = foo(42); auto s_copy = s; assert(s.foo() == 42); assert(s_copy.foo() == 42); }
He wants to deep-copy the struct, meaning copy the context pointer data. Meaning if you change 'i' in s, then s_copy's foo still returns 42. I don't think it is or should be doable. -Steve
Sep 12 2016
next sibling parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Tuesday, 13 September 2016 at 01:32:19 UTC, Steven 
Schveighoffer wrote:
 On 9/12/16 4:11 PM, Ali Çehreli wrote:
 On 09/10/2016 10:44 PM, Yuxuan Shui wrote:
 I recently noticed nested struct capture its context by 
 reference
 (which, BTW, is not mentioned at all here:
 https://dlang.org/spec/struct.html#nested).
" It has access to the context of its enclosing scope (via an added hidden field)." It needs to be a reference. Otherwise, you store the entire stack frame in the struct? That wouldn't be a "field". It also has write access to the context:
Why not just capture the variables that are actually been referenced? Also being a field doesn't put limits on the size of the "field". I like how C++ lambda lets you choose what variables to capture, and how are they captured. I'm little disappointed that D doesn't let me do the same.
Sep 13 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/13/16 3:42 PM, Yuxuan Shui wrote:
 On Tuesday, 13 September 2016 at 01:32:19 UTC, Steven Schveighoffer wrote:
 On 9/12/16 4:11 PM, Ali Çehreli wrote:
 On 09/10/2016 10:44 PM, Yuxuan Shui wrote:
 I recently noticed nested struct capture its context by reference
 (which, BTW, is not mentioned at all here:
 https://dlang.org/spec/struct.html#nested).
" It has access to the context of its enclosing scope (via an added hidden field)." It needs to be a reference. Otherwise, you store the entire stack frame in the struct? That wouldn't be a "field". It also has write access to the context:
Why not just capture the variables that are actually been referenced?
There's nothing in the language to prevent this optimization.
 Also being a field doesn't put limits on the size of the "field".
Again, could be clearer. But the fact that both the function and the struct affect the same data kind of dictates it needs to be a reference.
 I like how C++ lambda lets you choose what variables to capture, and how
 are they captured. I'm little disappointed that D doesn't let me do the
 same.
Not familiar with C++ lambda. You can always "specify" how to capture the data by directly declaring it: auto foo() { int x; static struct S { int x; } return S(x); } In D, if you have a closure, it's going to be heap allocated. Just the way it is. If you don't want that, you have to avoid them. -Steve
Sep 13 2016
parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Tuesday, 13 September 2016 at 20:00:40 UTC, Steven 
Schveighoffer wrote:
 On 9/13/16 3:42 PM, Yuxuan Shui wrote:
 [...]
There's nothing in the language to prevent this optimization.
 [...]
Again, could be clearer. But the fact that both the function and the struct affect the same data kind of dictates it needs to be a reference.
 [...]
Not familiar with C++ lambda. You can always "specify" how to capture the data by directly declaring it: auto foo() { int x; static struct S { int x; } return S(x); }
It just feels a bit tedious to do something manually while the compiler have enough information to do it for me.
 In D, if you have a closure, it's going to be heap allocated. 
 Just the way it is. If you don't want that, you have to avoid 
 them.

 -Steve
Sep 13 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/13/16 4:11 PM, Yuxuan Shui wrote:
 On Tuesday, 13 September 2016 at 20:00:40 UTC, Steven Schveighoffer wrote:
 Not familiar with C++ lambda. You can always "specify" how to capture
 the data by directly declaring it:

 auto foo()
 {
     int x;
     static struct S
     {
         int x;
     }
     return S(x);
 }
It just feels a bit tedious to do something manually while the compiler have enough information to do it for me.
Do what for you? How does it know that you don't want to use a closure and a reference to that instead? Note that all the internals for this are implementation defined. Given sufficient conditions, the compiler could "cheat" and allocate the data inside the struct itself instead. For example, if all referenced data was immutable. -Steve
Sep 13 2016
parent reply Yuxuan Shui <yshuiv7 gmail.com> writes:
On Tuesday, 13 September 2016 at 20:36:22 UTC, Steven 
Schveighoffer wrote:
 On 9/13/16 4:11 PM, Yuxuan Shui wrote:
 On Tuesday, 13 September 2016 at 20:00:40 UTC, Steven 
 Schveighoffer wrote:
 Not familiar with C++ lambda. You can always "specify" how to 
 capture
 the data by directly declaring it:

 auto foo()
 {
     int x;
     static struct S
     {
         int x;
     }
     return S(x);
 }
It just feels a bit tedious to do something manually while the compiler have enough information to do it for me.
Do what for you? How does it know that you don't want to use a closure and a reference to that instead? Note that all the internals for this are implementation defined. Given sufficient conditions, the compiler could "cheat" and allocate the data inside the struct itself instead. For example, if all referenced data was immutable. -Steve
For example, a common use case might be I want to capture everything by value. In stead of adding all the fields by hand and passing them to the constructor, I want the compiler to do it for me. i.e. I wish I could (borrowing C++ syntax): struct A[=] { ... } Then the context will be captured by value instead of reference.
Sep 13 2016
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 9/13/16 5:01 PM, Yuxuan Shui wrote:
 For example, a common use case might be I want to capture everything by
 value. In stead of adding all the fields by hand and passing them to the
 constructor, I want the compiler to do it for me.

 i.e. I wish I could (borrowing C++ syntax):

 struct A[=] {
    ...
 }

 Then the context will be captured by value instead of reference.
This is a valid enhancement. Why not try and ask for it? I don't know if the specific syntax would work for D, but the feature seems useful in some respects. -Steve
Sep 13 2016
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Tuesday, 13 September 2016 at 01:32:19 UTC, Steven 
Schveighoffer wrote:
 On 9/12/16 4:11 PM, Ali Çehreli wrote:
 On 09/10/2016 10:44 PM, Yuxuan Shui wrote:
 I recently noticed nested struct capture its context by 
 reference
 (which, BTW, is not mentioned at all here:
 https://dlang.org/spec/struct.html#nested).
He wants to deep-copy the struct, meaning copy the context pointer data. Meaning if you change 'i' in s, then s_copy's foo still returns 42. I don't think it is or should be doable. -Steve
with stack stomp no way that any hack could work, if any.
Sep 13 2016