Jump to page: 1 2
Thread overview
This one weird trick allows you to capture loop variables.
2 days ago
Ali Çehreli
2 days ago
Ali Çehreli
Oct 24
Meta
1 day ago
Imperatorn
Oct 30
Dukc
October 20

I thought of this when someone asked the age-old question about closures not capturing loop variables.

https://gist.github.com/schveiguy/b6b037bdfe74997743de81f8d3f4b92b

How does it work? It works because opApply is passed a lambda function generated by the compiler to implement the foreach body.

But because this is a separate function, when you close over that lambda, the lambda's stack is independently allocated on the heap for each loop iteration.

This doesn't exactly capture all variables, any variables in the enclosing scope are not duplicated (so it doesn't in effect capture what values were outside the loop body at that point in time). But isn't this the point?

In any case, thought it was interesting, and wondering if anyone's every thought of this before.

There are some lifetime and quality of life issues, but it's somewhat similar to std.parallelism in hooking opApply for nifty gain.

-Steve

October 19
I'm a bit sorry I implemented opApply. The conversion of the loop body to a lambda is a tricky beast, and in general such complex rewrites are not a good idea. The language should be straightforward.

October 19
On Saturday, October 19, 2024 8:29:53 PM MDT Walter Bright via Digitalmars-d wrote:
> I'm a bit sorry I implemented opApply. The conversion of the loop body to a lambda is a tricky beast, and in general such complex rewrites are not a good idea. The language should be straightforward.

Honestly, I've always found opApply to be very hard to understand. It's kind of like it's turning the foreach loop inside out, and it just hurts my brain. I'd probably understand it much better if I had to use it all the time, but at this point, I'd only ever use it in cases where ranges didn't make sense - and even then, I'd probably just elect to use a for loop instead of trying to take advantage of foreach. foreach is nice, but writing for loops isn't a big deal IMHO.

But for better or worse, we do have opApply, so I have to deal with it at least once in a while when someone else has used it. But such is life.

- Jonathan M Davis



October 20

On Sunday, 20 October 2024 at 02:14:14 UTC, Steven Schveighoffer wrote:

>

I thought of this when someone asked the age-old question about closures not capturing loop variables.

https://gist.github.com/schveiguy/b6b037bdfe74997743de81f8d3f4b92b

How does it work? It works because opApply is passed a lambda function generated by the compiler to implement the foreach body.

But because this is a separate function, when you close over that lambda, the lambda's stack is independently allocated on the heap for each loop iteration.

This is cute and all, but the correct solution is to fix the damn compiler. The fact that this is necessary in the first place is an embarrassment.

October 20

On Sunday, 20 October 2024 at 17:48:15 UTC, Paul Backus wrote:

>

This is cute and all, but the correct solution is to fix the damn compiler. The fact that this is necessary in the first place is an embarrassment.

When I first encountered closures in D and saw how easily they capture surrounding variables it felt like magic.

Nowadays I dislike them because they allocate behind the scene, and you still get this odd foreach behavior mentioned here - which, to be fair, however unintuitive, I believe to be correct given the interplay of features.

The only good solution I see is to get rid of implicit captures and instead require explicit declaration of what and how to capture, i.e. by ref or by value.

October 21
On 10/20/24 20:14, Sebastiaan Koppe wrote:
> 
> Nowadays I dislike them because they allocate behind the scene, and you still get this odd foreach behavior mentioned here - which, to be fair, however unintuitive, I believe to be correct given the interplay of features.

The odd `foreach` behavior is a long-standing compiler bug.
The behavior with `opApply` is indeed the only correct behavior, no interplay of features has to be considered.
October 21
On 10/20/24 04:29, Walter Bright wrote:
> I'm a bit sorry I implemented opApply.

I am not.

> The conversion of the loop body to a lambda is a tricky beast, and in general such complex rewrites are not a good idea. The language should be straightforward.
> 

As someone who has also implemented `opApply`, I do think it is quite straightforward. It's just internal iteration with support for multiple ways to exit the loop, encoded using numerical indices.
October 20
On 10/19/2024 7:58 PM, Jonathan M Davis wrote:
> it just hurts my brain.

It hurts mine, too.

There's a lot of complex, obtuse code to implement it.

October 20
On 10/20/2024 3:45 PM, Timon Gehr wrote:
> As someone who has also implemented `opApply`, I do think it is quite straightforward. It's just internal iteration with support for multiple ways to exit the loop, encoded using numerical indices.

That's because you're smarter than I am, Timon. And I'm not joking.

I implemented it as a way to deal with visiting each node of a binary tree. Doing that with a range is clunky and unappealing.
October 23
On Sunday, 20 October 2024 at 22:45:24 UTC, Timon Gehr wrote:
> As someone who has also implemented `opApply`, I do think it is quite straightforward. It's just internal iteration with support for multiple ways to exit the loop, encoded using numerical indices.

Do you have any suggestions or insights how we could resolve its rather poor compatibility with the attribute soup?
« First   ‹ Prev
1 2