www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Local variable inside delegate literal

reply Daniel <yebbliesnospam gmail.com> writes:
I'm writing some gui code, and am currently trying to make something equivalent
to this:

int delegate()[] funcs;
funcs.length = 3;

foreach(i, ref f; funcs)
{
  f = int() { return i; }
}

foreach(f; funcs)
{
  writeln(f());
}

Prints:
3
3
3

I want it to print
0
1
2

Is there anyway to get this behaviour using delegate literals initialized with
a runtime loop?
Dec 22 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Daniel:

 I'm writing some gui code, and am currently trying to make something
equivalent to this:
 
 int delegate()[] funcs;
 funcs.length = 3;
 
 foreach(i, ref f; funcs)
 {
   f = int() { return i; }
 }
 
 foreach(f; funcs)
 {
   writeln(f());
 }

This is D2 code that actually compiles: import std.stdio: writeln; void main() { auto funcs = new int delegate()[3]; foreach (i, ref f; funcs) f = { return cast(int)i; }; foreach (f; funcs) writeln(f()); } This is a good version in D2: import std.stdio: writeln; class Foo { int i; this(int i) { this.i = i; } int opCall() { return this.i; } } void main() { auto funcs = new Foo[3]; foreach (i, ref f; funcs) f = new Foo(i); foreach (f; funcs) writeln(f()); } Or even cheaper: import std.stdio: writeln; struct Foo { int i; this(int i) { this.i = i; } int opCall() { return this.i; } } void main() { auto funcs = new Foo[3]; foreach (i, ref f; funcs) f = Foo(i); foreach (f; funcs) writeln(f()); } Often the better code is not the most compact one, but the most explicit one. Bye, bearophile
Dec 23 2009
parent Daniel <yebbliesnospam gmail.com> writes:
bearophile Wrote:

 Daniel:
 
 I'm writing some gui code, and am currently trying to make something
equivalent to this:
 
 int delegate()[] funcs;
 funcs.length = 3;
 
 foreach(i, ref f; funcs)
 {
   f = int() { return i; }
 }
 
 foreach(f; funcs)
 {
   writeln(f());
 }

This is D2 code that actually compiles: import std.stdio: writeln; void main() { auto funcs = new int delegate()[3]; foreach (i, ref f; funcs) f = { return cast(int)i; }; foreach (f; funcs) writeln(f()); } This is a good version in D2: import std.stdio: writeln; class Foo { int i; this(int i) { this.i = i; } int opCall() { return this.i; } } void main() { auto funcs = new Foo[3]; foreach (i, ref f; funcs) f = new Foo(i); foreach (f; funcs) writeln(f()); } Or even cheaper: import std.stdio: writeln; struct Foo { int i; this(int i) { this.i = i; } int opCall() { return this.i; } } void main() { auto funcs = new Foo[3]; foreach (i, ref f; funcs) f = Foo(i); foreach (f; funcs) writeln(f()); } Often the better code is not the most compact one, but the most explicit one. Bye, bearophile

I actually needed it to be a delegate to interact with the rest of my code, but I used the idea of making a copy of the index variable each loop iteration, using a generating function returning a closure. Thanks for your help. import std.stdio: writeln; void main() { auto funcs = new int delegate()[3]; int delegate() makedg(int i) { return { return i; }; } foreach (i, ref f; funcs) f = makedg(i); foreach (f; funcs) writeln(f()); } Or void main() { auto funcs = new int delegate()[3]; foreach (i, ref f; funcs) f = (int i) { return { return i; }; }(i); foreach (f; funcs) writeln(f()); }
Dec 23 2009
prev sibling next sibling parent downs <default_357-line yahoo.de> writes:
Daniel wrote:
 I'm writing some gui code, and am currently trying to make something
equivalent to this:
 
 int delegate()[] funcs;
 funcs.length = 3;
 
 foreach(i, ref f; funcs)
 {
   f = int() { return i; }
 }
 
 foreach(f; funcs)
 {
   writeln(f());
 }
 
 Prints:
 3
 3
 3
 
 I want it to print
 0
 1
 2
 
 Is there anyway to get this behaviour using delegate literals initialized with
a runtime loop?

This is how you do it in 1.0: import std.stdio, std.bind; void main() { auto funcs = new int delegate()[3]; foreach (i, ref f; funcs) f = bind((int i) { return i; }, i).ptr(); foreach (f; funcs) writefln(f()); } --outputs-- 0 1 2
Dec 23 2009
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Daniel wrote:
 int delegate()[] funcs;
 funcs.length = 3;
 
 foreach(i, ref f; funcs)
 {
   f = int() { return i; }
 }
 
 foreach(f; funcs)
 {
   writeln(f());
 }

First, there are syntax errors in your example. It should be f = delegate int() { return i; }; Second, this works in D2: foreach(i, ref f; funcs) { void blah() { auto j = i; f = delegate int() { return j; }; } blah(); } But this doesn't, outputs 2, 2, 2: foreach(i, ref f; funcs) { auto j = i; f = delegate int() { return j; }; } And this crashes: foreach(i, ref f; funcs) { ({ auto j = i; f = delegate int() { return j; }; })(); } I think these 3 variants should be equivalent.
Dec 23 2009