digitalmars.D - D2 full closure?
- Frank Benoit (23/23) Jul 13 2008 With DMD 2.015:
- Jason House (2/30) Jul 13 2008 I could have sworn there was a bug report to make this work like you wan...
- Frank Benoit (6/38) Jul 14 2008 Yes i know there are ways to make it work.
- Jason House (3/43) Jul 14 2008 If none of the D language authors reply in this thread or post to the bu...
- Walter Bright (2/3) Jul 15 2008 No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
- Frank Benoit (2/6) Jul 15 2008 ok, now it is. (#2228)
- BCS (24/30) Jul 15 2008 What?!! The value for the delegates are copied at the point of the '&'?
- downs (5/18) Jul 15 2008 No, the problem is something else.
- Walter Bright (8/27) Jul 15 2008 No, they are never copied. The delegates should refer directly to the
- BCS (31/48) Jul 15 2008 Oh crud, I read it wrong.
- Walter Bright (5/46) Jul 15 2008 All that happens is the stack frame is put on the heap. It doesn't
- BCS (6/52) Jul 16 2008 Well in that cases why would it be expected that the const value be froz...
With DMD 2.015: alias void delegate() Runner; void main(){ Runner[] runner; for( int i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d", ci ); } } foreach( runner; runners ){ runner(); } } Output: run with ci=2 run with ci=2 run with ci=2 Is this output expected? From the technical point yes, because i know how it is implemented. But is this expected in the sense of "Full closure"? In Java, if ci would be "final" and the delegate an anonymous class, the output would be 0,1,2.
Jul 13 2008
Frank Benoit Wrote:With DMD 2.015: alias void delegate() Runner; void main(){ Runner[] runner; for( int i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d", ci ); } } foreach( runner; runners ){ runner(); } } Output: run with ci=2 run with ci=2 run with ci=2 Is this output expected? From the technical point yes, because i know how it is implemented. But is this expected in the sense of "Full closure"? In Java, if ci would be "final" and the delegate an anonymous class, the output would be 0,1,2.I could have sworn there was a bug report to make this work like you want. Another alternative is to use bind.
Jul 13 2008
Jason House schrieb:Frank Benoit Wrote:Yes i know there are ways to make it work. But my question is, shouldn't it work in this code? Is it a bug or not? Is it ok that the constant is changing the value? Should each delegate get its own heap allocated copy of the stack frame?With DMD 2.015: alias void delegate() Runner; void main(){ Runner[] runner; for( int i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d", ci ); } } foreach( runner; runners ){ runner(); } } Output: run with ci=2 run with ci=2 run with ci=2 Is this output expected? From the technical point yes, because i know how it is implemented. But is this expected in the sense of "Full closure"? In Java, if ci would be "final" and the delegate an anonymous class, the output would be 0,1,2.I could have sworn there was a bug report to make this work like you want. Another alternative is to use bind.
Jul 14 2008
Frank Benoit wrote:Jason House schrieb:If none of the D language authors reply in this thread or post to the bug report, we'll never know what was intended.Frank Benoit Wrote:Yes i know there are ways to make it work. But my question is, shouldn't it work in this code? Is it a bug or not? Is it ok that the constant is changing the value? Should each delegate get its own heap allocated copy of the stack frame?With DMD 2.015: alias void delegate() Runner; void main(){ Runner[] runner; for( int i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d", ci ); } } foreach( runner; runners ){ runner(); } } Output: run with ci=2 run with ci=2 run with ci=2 Is this output expected? From the technical point yes, because i know how it is implemented. But is this expected in the sense of "Full closure"? In Java, if ci would be "final" and the delegate an anonymous class, the output would be 0,1,2.I could have sworn there was a bug report to make this work like you want. Another alternative is to use bind.
Jul 14 2008
Frank Benoit wrote:Is this output expected?No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
Jul 15 2008
Walter Bright schrieb:Frank Benoit wrote:Is this output expected?No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
Jul 15 2008
Reply to Walter,Frank Benoit wrote:What?!! The value for the delegates are copied at the point of the '&'? That seems more like currying to me. In general I the behavior I would expect is that the values would never be copied. I would expect that the outer function would store some of it's variable on the heap and then all access (via delegate or in the outer function) would be to the same values. Why is the reverse preferable? the proposed-to-be-correct behavior precludes having more than one delegate operate on the same stuff or more generally, have side effects on the outer function variables: int delegate() DoIt() { int j = 10; int i = 0 int B(){return i+=4;} auto dg = &B; while(j) { dg(); if(j & 0x01) i--; } return dg; }Is this output expected?No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
Jul 15 2008
BCS wrote:Reply to Walter,No, the problem is something else. Currently, closures are apparently formed with the function body. However, in this case, it is reasonable to expect them to be instead formed with *the surrounding scope*, especially since, in the case of loops, it sort of behaves like a function being called anyway. (like a half-way cross between scope and function). --downsFrank Benoit wrote:What?!! The value for the delegates are copied at the point of the '&'? That seems more like currying to me.Is this output expected?No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
Jul 15 2008
BCS wrote:Reply to Walter,No, they are never copied. The delegates should refer directly to the variable which, in the case of a closure, gets allocated on the heap rather than the stack frame.Frank Benoit wrote:What?!! The value for the delegates are copied at the point of the '&'?Is this output expected?No, it's a bug. The output should be 0,1,2. Is it on bugzilla?That seems more like currying to me. In general I the behavior I would expect is that the values would never be copied. I would expect that the outer function would store some of it's variable on the heap and then all access (via delegate or in the outer function) would be to the same values. Why is the reverse preferable?It isn't. The behavior you expect *is* the current behavior. The particular const behavior is (I haven't delved into it) the compiler incorrectly deciding that a const variable wouldn't need to be put on the heap.
Jul 15 2008
Reply to Walter,BCS wrote:Oh crud, I read it wrong. OTOH that problem is even worse than the issue I was thinking of: is this valid? does it generate a different heap frame for each time through the loop? alias void delegate() Runner; void main(){ Runner[] runner; int i; for(i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d, i=%d", ci, i ); } } foreach( runner; runners ){ runner(); } } is this valid? void main() { Runner a; { int i = 5; a = {i++;} } { int j = 6; a(); assert(j==6); } }Reply to Walter,No, they are never copied. The delegates should refer directly to the variable which, in the case of a closure, gets allocated on the heap rather than the stack frame.Frank Benoit wrote:What?!! The value for the delegates are copied at the point of the '&'?Is this output expected?No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
Jul 15 2008
BCS wrote:Oh crud, I read it wrong. OTOH that problem is even worse than the issue I was thinking of: is this valid?Yes.does it generate a different heap frame for each time through the loop?All that happens is the stack frame is put on the heap. It doesn't allocate new heap frames in a loop.alias void delegate() Runner; void main(){ Runner[] runner; int i; for(i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d, i=%d", ci, i ); } } foreach( runner; runners ){ runner(); } } is this valid?Yes.void main() { Runner a; { int i = 5; a = {i++;} } { int j = 6; a(); assert(j==6); } }
Jul 15 2008
Reply to Walter,BCS wrote:Well in that cases why would it be expected that the const value be frozen? Each time through the loop the value is stored on that stack in the same place. At then end of the loop, all the delegates point print out a value from the same location.Oh crud, I read it wrong. OTOH that problem is even worse than the issue I was thinking of: is this valid?Yes.does it generate a different heap frame for each time through the loop?All that happens is the stack frame is put on the heap. It doesn't allocate new heap frames in a loop.Couldn't i and j overlap?alias void delegate() Runner; void main(){ Runner[] runner; int i; for(i = 0; i < 3; i++ ){ const int ci = i; runners ~= delegate(){ writefln( "run with ci=%d, i=%d", ci, i ); } } foreach( runner; runners ){ runner(); } } is this valid?Yes.void main() { Runner a; { int i = 5; a = {i++;} } { int j = 6; a(); assert(j==6); } }
Jul 16 2008