Closures and loop scope

Idan Arye GenericNPC at gmail.com
Tue Jun 4 12:55:38 PDT 2013


On Tuesday, 4 June 2013 at 19:42:39 UTC, Adam D. Ruppe wrote:
> On Tuesday, 4 June 2013 at 19:19:57 UTC, Idan Arye wrote:
>> Can this be fixed? *Should* this be fixed?
>
> For what it's worth, Javascript works the same way. So I've 
> come to the pattern of having a function return a function when 
> it is looping in both languages.
>
> So while it might not be ideal, it isn't totally unexpected 
> since other languages do it too.

Ruby is the most interesting:

     arr=[]
     for i in 0...5
         arr<< lambda{i}
     end

     puts arr.map{|e|e.call}.to_s

prints [4, 4, 4, 4, 4], because it uses the built-in for loop, so 
`i` is reused in all iterations. On the other hand:

     arr=[]
     (0...5).each do|i|
         arr<< lambda{i}
     end

     puts arr.map{|e|e.call}.to_s

prints [0, 1, 2, 3, 4], because each call to the rubyblock has 
it's own stack frame and it's own `i`. This can also be done in D:


     auto arr=new ulong delegate()[5];

     auto iotaDelegate(T...)(T args){
         return (int delegate(ref ulong) dlg){
             foreach(i;iota(args)){
                 dlg(i);
             }
             return 0;
         };
     }

     foreach(i;iotaDelegate(arr.length)){
         arr[i]=()=>i;
     }

     writeln(arr.map!`a()`());

This prints [0, 1, 2, 3, 4], because each iteration of the 
foreach is actually an function call, so it has it's own stack 
frame.


More information about the Digitalmars-d mailing list