Closures and loop scope

Timon Gehr timon.gehr at gmx.ch
Tue Jun 4 14:24:51 PDT 2013


On 06/04/2013 11:03 PM, Nick Sabalausky wrote:
> On Tue, 04 Jun 2013 21:19:56 +0200
> "Idan Arye" <GenericNPC at gmail.com> 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`.
>>
>
> I think the problem is simply a misunderstanding of closures.
> ...

I believe what you explain is exactly what he suspected is happening.

> ...
>
> So when you put the delegate creation in a loop:
>
>      foreach(a; iota(0..6))
>          dg = () => a;
>
> It *is* expected that you're *not* sticking 0, 1, 2, 3, etc inside the
> delegate. That's because you're not evaluating "a" *at all* here,
> you're just crerates a delegate that *refers* to "a" itself. You're
> just creating the exact same delegate five times. In other words:
>
> You're just saying:
> Store the following set of instructions into 'dg': "Read the value of
> 'a' and then return it."
>
> You're *not* saying:
> Read the value of 'a' and *then* create a delegate that returns that
> value.
>
>

'a' refers to a different location for every loop iteration. This is a 
language change in 2.063.



More information about the Digitalmars-d mailing list