digitalmars.D - Local variable inside delegate literal
- Daniel (20/20) Dec 22 2009 I'm writing some gui code, and am currently trying to make something equ...
 - bearophile (41/55) Dec 23 2009 This is D2 code that actually compiles:
 - Daniel (23/100) Dec 23 2009 I actually needed it to be a delegate to interact with the rest of my co...
 - downs (14/40) Dec 23 2009 This is how you do it in 1.0:
 - Sergey Gromov (27/39) Dec 23 2009 First, there are syntax errors in your example. It should be
 
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
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
bearophile Wrote:Daniel: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()); }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
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
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








 
 
 
 Daniel <yebbliesnospam gmail.com> 