| Thread overview | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 13, 2008 D2 full closure? | ||||
|---|---|---|---|---|
| ||||
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.
| ||||
July 13, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Frank Benoit | 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.
| |||
July 14, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jason House | Jason House schrieb:
> 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.
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?
| |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Frank Benoit | Frank Benoit wrote:
> Jason House schrieb:
>> 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.
>
> 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?
If none of the D language authors reply in this thread or post to the bug report, we'll never know what was intended.
| |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Frank Benoit | Frank Benoit wrote:
> Is this output expected?
No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
| |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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?
ok, now it is. (#2228)
| |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Reply to Walter,
> Frank Benoit wrote:
>
>> Is this output expected?
>>
> No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
>
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;
}
| |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to BCS | BCS wrote:
> Reply to Walter,
>
>> Frank Benoit wrote:
>>
>>> Is this output expected?
>>>
>> No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
>>
>
> What?!! The value for the delegates are copied at the point of the '&'?
>
> That seems more like currying to me.
>
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).
--downs
| |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to BCS | BCS wrote: > Reply to Walter, > >> Frank Benoit wrote: >> >>> Is this output expected? >>> >> No, it's a bug. The output should be 0,1,2. Is it on bugzilla? >> > > What?!! The value for the delegates are copied at the point of the '&'? 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. > > 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. | |||
July 15, 2008 Re: D2 full closure? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Reply to Walter,
> BCS wrote:
>
>> Reply to Walter,
>>
>>> Frank Benoit wrote:
>>>
>>>> Is this output expected?
>>>>
>>> No, it's a bug. The output should be 0,1,2. Is it on bugzilla?
>>>
>> What?!! The value for the delegates are copied at the point of the
>> '&'?
>>
> 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.
>
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);
}
}
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply