3 ms·
> What you actually should deliver is an implementation where each time around the loop there's a new variable named Goose, that variable goes away at the end o
by lelanthran 2mo ago
> What you actually should deliver is an implementation where each time around the loop there's a new variable named Goose, that variable goes away at the end of that iteration and will be replaced by the next one, with the same exact name.
Is this because a closure inside a loop will capture a reference to `Goose`?
I think that this is a capture problem not a variable problem. The closure should always do the right thing and capture the value of all variables (not just ones inside the loop), instead of capturing the reference to the variables.
Then the general problem is fixed to match what developers expect, instead of a specific instance of that class of problems being fixed and working differently to how other captured variables work.
- tialaramex 2mo ago> I think that this is a capture problem not a variable problem. The closure should always do the right thing and capture the value of all variables (not just ones inside the loop), instead of capturing the reference to the variables. Now your "lalanthran closures" can't mutate the world because they work exclusively with copies not references, if they try to mutate something then whatever they're touching was just a copy not the real thing.
- lelanthran 2mo ago> Now your "lalanthran closures" can't mutate the world because they work exclusively with copies not references, if they try to mutate something then whatever they're touching was just a copy not the real thing. That is true. I still don't like the idea of "Here is a general rule. It applies everywhere but $HERE." Whether that general rule is "All captures are by value" or "All captures are by reference", the rule should not have exceptions based on context in the code. A better tradeoff would be to have the general rule (whatever it is) apply everywhere, along with syntax for capturing (or not, depending what the default is). I'd rather have it grab everything by value, and for those things that are susceptible to race conditions (because more than one closure is modifying it), explicitly annotate it with a sigil (`&`, or a keyword, or similar). I mean, in pseudocode, when I see: ... variables x, y and z are declared and used in this scope ... return (x, y, x) => { ... } I don't want to have to examine the surrounding scope to know whether or not `y` is susceptible to a race. I'd rather just see: ... variables x, y and z are declared and used in this scope ... return (x, &y, x) => { ... } An alternative viewpoint is that many languages have immutable variables and they seem to be getting along just fine without needing mutation on variables, shared or otherwise.
- tialaramex 2mo ago> the rule should not have exceptions based on context in the code. But the rules didn't and still don't have any such exceptions. > A better tradeoff would be to have the general rule (whatever it is) apply everywhere, along with syntax for capturing (or not, depending what the default is) This "solution" is how it works in C++. We can thus castigate the programmer for writing the wrong runes in their captures list and never for a moment doubt that we got it right when we introduced so very many footguns... Tony Hoare's observation applies "One way is to make the program so simple, there are obviously no errors. The other is to make it so complicated, there are no obvious errors." > An alternative viewpoint is that many languages have immutable variables and they seem to be getting along just fine without needing mutation on variables, shared or otherwise. Sure, and one of the astonishing things in C# or Go before they fixed this is that you can indeed have immutable variables which change, even though that's silly - the language can decide that you mustn't change Goose, but it doesn't need to obey its own rules because it will change it for each loop iteration.
- Animats 2mo agoThe interior of a for-loop is only a scope, not a closure. In most non-dynamic languages you can't package up the state and hold onto it beyond the life of the loop, which is what closures are for. Most trouble in this area came from the iteration variable outliving the loop. That's not good when the iteration variable is a pointer. In C, it often is, and at the end of the loop, it points to an invalid address. It was a change to C (when?) to make the iteration variable go out of scope before code after the loop could get at it.