Closures and loop scope

Nick Sabalausky SeeWebsiteToContactMe at semitwist.com
Tue Jun 4 14:57:39 PDT 2013


On Tue, 04 Jun 2013 22:52:27 +0200
Timon Gehr <timon.gehr at gmx.ch> wrote:

> On 06/04/2013 09:19 PM, Idan Arye wrote:
> > Consider the following code. What will it print?
> >
> >      auto arr=new ulong delegate()[5];
> >
> >      foreach(i;0..arr.length){
> >          arr[i]=()=>i;
> >      }
> >
> >      writeln(arr.map!`a()`());
> >
> > It is natural to expect that it will print [0, 1, 2, 3, 4], but it
> > actually prints [5, 5, 5, 5, 5]. The reason is obvious - all the
> > delegates refer to the same `i` in their closures, and at the end
> > of the loop that `i` is set to `5`.
> >
> > ...
> 
> It is not that obvious. They refer to different i's that happen to 
> reside at the same place in the stack frame. It's a bug.
> 
> It is more obvious that it is a bug given this code snippet:
> 
> import std.stdio, std.algorithm;
> 
> void main(){
>      auto arr=new ulong delegate()[5];
>      foreach(immutable i;0..arr.length){
>           arr[i]={auto j=i;return {assert(j==i); return i;};}();
>      }
>      writeln(arr.map!`a()`());
> }
> 
> As you can see, 'i' mutates even though it is declared immutable.
> 

Keep in mind that this exhibits the same "mutating immutable" behavior:

// Prints 0, 1, 2, 3, 4, even though i is immutable
foreach(immutable i; 0..5){
    writeln(i);

It's questionable as to whether that's really a problem. And even if it
is a problem, it would *only* be because you make i immutable. So
this is irrelevant to the OP's examples because:

1. He didn't use immutable, and

2. A delegate is *expected* to read the values inside its closure at
the time of delegate *invocation*, not at the time of delegate creation.

> >...
> 
> Yes. Yes.
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=2043

That refers to a local defined within the loop, not the iteration
variable itself, which is different from the OP. Also, it's
questionable that there's any problem there *other* than the immutable
stuff.




More information about the Digitalmars-d mailing list