| Thread overview | |||||||||
|---|---|---|---|---|---|---|---|---|---|
|
July 05, 2012 A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Attachments:
| Hi, My test code: > import std.stdio; > void main() { > void delegate()[] functions; > foreach (i; 0 .. 5) { > functions ~= { > printf("%d\n", i); > }; } > foreach (func; functions) { > func(); > } > } output: $ dmd DMD64 D Compiler v2.059 ... $ ./main > 5 > 5 > 5 > 5 > 5 Seems like all delegations shared a stack variable, I think delegation must copy the value into its context. I can avoid it: void delegate() createDelegate(int i) { > void exec() { > printf("%d\n", i); > } > return &exec; > } > foreach (i; 0 .. 5) { > functions ~= createDelegate(i); > } But hope for improve it. Best regards, -- Li Jie | |||
July 05, 2012 Re: A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Posted in reply to lijie | lijie:
>> import std.stdio;
>> void main() {
>> void delegate()[] functions;
>> foreach (i; 0 .. 5) {
>> functions ~= {
>> printf("%d\n", i);
>> };
>
> }
>> foreach (func; functions) {
>> func();
>> }
>> }
import std.stdio;
void main() {
void delegate()[] functions;
foreach (i; 0 .. 5)
functions ~= ((int j) => { printf("%d\n", j); })(i);
foreach (func; functions)
func();
}
Bye,
bearophile
| |||
July 05, 2012 Re: A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Posted in reply to lijie | 05.07.2012 9:54, lijie пишет: > Hi, > > My test code: > > import std.stdio; > void main() { > void delegate()[] functions; > foreach (i; 0 .. 5) { > functions ~= { > printf("%d\n", i); > }; > > } > foreach (func; functions) { > func(); > } > } > > > output: > 5 > 5 > 5 > 5 > 5 This program behaves as expected. Just like C# program that will give the same output: --- delegate void MyFunc(); class Program { static void Main() { var funcs = new MyFunc[5]; for (int i = 0; i < funcs.Length; ++i) funcs[i] = new MyFunc(() => System.Console.WriteLine(i)); foreach (var f in funcs) f(); } } --- because "i" is the same for every iteration. Different situation is for such C# loop: --- for (int i = 0; i < funcs.Length; ++i) { int t = i; funcs[i] = new MyFunc(() => System.Console.WriteLine(t)); } --- where "t" is local for scope. Here C# behaves correctly, but D doesn't. This D loop --- foreach(i; 0 .. 5) { int t = i; functions ~= { printf("%d\n", t); }; } --- prints "4" five times. It's Issue 2043: http://d.puremagic.com/issues/show_bug.cgi?id=2043 I'm not posting workaround here because bearophile already did it. -- Денис В. Шеломовский Denis V. Shelomovskij | |||
July 06, 2012 Re: A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile Attachments:
| On Thu, Jul 5, 2012 at 3:36 PM, bearophile <bearophileHUGS@lycos.com> wrote:
> lijie:
>
>
> import std.stdio;
>>> void main() {
>>> void delegate()[] functions;
>>> foreach (i; 0 .. 5) {
>>> functions ~= {
>>> printf("%d\n", i);
>>> };
>>>
>>
>> }
>>
>>> foreach (func; functions) {
>>> func();
>>> }
>>> }
>>>
>>
>
> import std.stdio;
>
> void main() {
> void delegate()[] functions;
>
> foreach (i; 0 .. 5)
> functions ~= ((int j) => { printf("%d\n", j); })(i);
>
> foreach (func; functions)
> func();
> }
>
>
Thanks bearophile.
Best regards,
-- Li Jie
| |||
July 06, 2012 Re: A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Denis Shelomovskij Attachments:
| On Thu, Jul 5, 2012 at 4:26 PM, Denis Shelomovskij < verylonglogin.reg@gmail.com> wrote:
> Different situation is for such C# loop:
> ---
> for (int i = 0; i < funcs.Length; ++i)
> {
> int t = i;
> funcs[i] = new MyFunc(() => System.Console.WriteLine(t));
> }
> ---
> where "t" is local for scope. Here C# behaves correctly, but D doesn't. This D loop
> ---
> foreach(i; 0 .. 5) {
> int t = i;
> functions ~= { printf("%d\n", t); };
> }
> ---
> prints "4" five times. It's Issue 2043: http://d.puremagic.com/issues/**show_bug.cgi?id=2043 <http://d.puremagic.com/issues/show_bug.cgi?id=2043>
>
How to distinguish which variables will be copied to the closure context?
I think this is a scope rule, in the previous code, there are three
variables:
1. function arguments
2. loop variables
3. local variables
Seems only function parameters is copied. In C#, local variables is
copied. There
are other rules? And why is the loop variable not local?
Thanks.
Best regards,
-- Li Jie
| |||
July 06, 2012 Re: A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Posted in reply to lijie | On 07/06/2012 05:14 AM, lijie wrote: > On Thu, Jul 5, 2012 at 4:26 PM, Denis Shelomovskij > <verylonglogin.reg@gmail.com <mailto:verylonglogin.reg@gmail.com>> wrote: > > Different situation is for such C# loop: > --- > for (int i = 0; i < funcs.Length; ++i) > { > int t = i; > funcs[i] = new MyFunc(() => System.Console.WriteLine(t)); > } > --- > where "t" is local for scope. Here C# behaves correctly, but D > doesn't. This D loop > --- > foreach(i; 0 .. 5) { > int t = i; > functions ~= { printf("%d\n", t); }; > } > --- > prints "4" five times. It's Issue 2043: > http://d.puremagic.com/issues/__show_bug.cgi?id=2043 > <http://d.puremagic.com/issues/show_bug.cgi?id=2043> > > How to distinguish which variables will be copied to the closure context? > They are not copied, they are stored there. > I think this is a scope rule, in the previous code, there are three > variables: > 1. function arguments > 2. loop variables > 3. local variables > Seems only function parameters is copied. In C#, local variables is > copied. There are other rules? And why is the loop variable not local? > > Thanks. > > Best regards, > > -- Li Jie It is simple. Variable declarations introduce a new variable. Closures that reference the same variable will see the same values. ---- foreach(i; 0..3) { functions~={writeln(i);}; } is the same as for(int i=0;i<3;i++) { functions~={writeln(i);}; } is the same as {int i=0;for(;i<3;i++) { functions~={writeln(i);}; }} is the same as { int i=0; { functions~={writeln(i);}; } i++; { functions~={writeln(i);}; } i++; { functions~={writeln(i);}; } i++; } ---- foreach(i; 0..3){ int j=i; functions~={writeln(j);}; } is the same as for(int i=0;i<3;i++){ int j=i; functions~={writeln(j);}; } is the same as {int i=0;for(i<3;i++){ int j=i; functions~={writeln(j);}; } is the same as { int i=0; { int j=i; functions~={writeln(j);}; } i++; { int j=i; functions~={writeln(j);}; } i++; { int j=i; functions~={writeln(j);}; } i++; } ---- I think it is quite intuitive. | |||
July 06, 2012 Re: A delegate problem, create delegation in loop | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr Attachments:
| On Fri, Jul 6, 2012 at 3:06 PM, Timon Gehr <timon.gehr@gmx.ch> wrote:
>
> It is simple. Variable declarations introduce a new variable. Closures that reference the same variable will see the same values.
>
> ----
>
> foreach(i; 0..3) { functions~={writeln(i);}; }
>
> is the same as
>
> for(int i=0;i<3;i++) { functions~={writeln(i);}; }
>
> is the same as
>
> {int i=0;for(;i<3;i++) { functions~={writeln(i);}; }}
>
> is the same as
>
> {
> int i=0;
> { functions~={writeln(i);}; }
> i++;
> { functions~={writeln(i);}; }
> i++;
> { functions~={writeln(i);}; }
> i++;
> }
>
>
> ----
>
> foreach(i; 0..3){ int j=i; functions~={writeln(j);}; }
>
> is the same as
>
> for(int i=0;i<3;i++){ int j=i; functions~={writeln(j);}; }
>
> is the same as
>
> {int i=0;for(i<3;i++){ int j=i; functions~={writeln(j);}; }
>
> is the same as
>
> {
> int i=0;
> { int j=i; functions~={writeln(j);}; }
> i++;
> { int j=i; functions~={writeln(j);}; }
> i++;
> { int j=i; functions~={writeln(j);}; }
> i++;
> }
>
> ----
>
> I think it is quite intuitive.
>
>
Understood, thanks.
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply