August 29
On Fri, Aug 29, 2025 at 10:51:10PM +0000, Steven Schveighoffer via Digitalmars-d wrote:
> On Friday, 29 August 2025 at 22:28:17 UTC, H. S. Teoh wrote:
> > Now, JS is certainly not a model language to follow, but it's interesting how it shares with D the same issue over closures involving loop variables.
> > 
> > I guess that means we're not alone. :-P  Even though this situation is definitely not ideal.
> 
> Oh yeah, JS has similar behavior. You get the desired behavior by using `let` at the variable declaration. Otherwise, it becomes a regular declaration (one instance per function).
> 
> I think your original code will work as you want with:
> 
> ```js
> for (let button of buttons) {
> ```

Oooh yes, that *is* exactly what I was looking for.  I already got bitten before by for(... of) without `let`... still haven't learned my lesson, it seems.


> Would be nice to have a similar trick for D...

Sneaky syntax proposal:

```d
	void delegate()[] dgs;
	foreach (scope i; 0 .. 100) {	// N.B. `scope`
		dgs ~= () {
			writefln("%d", i); // <-- closes over independent instance of `i`
		};
	}
```

;-)


T

-- 
Give a man a fish, and he eats once. Teach a man to fish, and he will sit forever.
August 30
On 8/30/25 01:17, H. S. Teoh wrote:
> On Fri, Aug 29, 2025 at 10:51:10PM +0000, Steven Schveighoffer via Digitalmars-d wrote:
>> On Friday, 29 August 2025 at 22:28:17 UTC, H. S. Teoh wrote:
>>> Now, JS is certainly not a model language to follow, but it's
>>> interesting how it shares with D the same issue over closures
>>> involving loop variables.
>>>
>>> I guess that means we're not alone. :-P  Even though this situation
>>> is definitely not ideal.
>>
>> Oh yeah, JS has similar behavior. You get the desired behavior by
>> using `let` at the variable declaration. Otherwise, it becomes a
>> regular declaration (one instance per function).
>>
>> I think your original code will work as you want with:
>>
>> ```js
>> for (let button of buttons) {
>> ```
> 
> Oooh yes, that *is* exactly what I was looking for.  I already got
> bitten before by for(... of) without `let`... still haven't learned my
> lesson, it seems.
> 
> 
>> Would be nice to have a similar trick for D...
> 
> Sneaky syntax proposal:
> 
> ```d
> 	void delegate()[] dgs;
> 	foreach (scope i; 0 .. 100) {	// N.B. `scope`
> 		dgs ~= () {
> 			writefln("%d", i); // <-- closes over independent instance of `i`
> 		};
> 	}
> ```
> 
> ;-)
> 
> 
> T
> 

The variable `i` is already a variable local to the loop body. The fact that it is shared between loop iterations is a form of memory corruption, it is not really comparable to the JS case.

JS just did not use to even have variables that are local to a scope, which they more or less fixed with `let`/`const`. D does not have this problem, we do have local variables, closures are just not implemented correctly.

I think the problem really isn't that there is no dedicated syntax to make it not corrupt memory, it's that it does not just work, even if you do declare a local intermediate variable in the loop body. x)