The rationale for the current behavior of re-using the loop variable was always performance. The claim was that allocating a new value for each iteration of a loop was costly enough to out-weigh the various points of confusion that are described in the link. So I would expect that a proposal to change this behavior would include a pretty thorough analysis of the performance impact. But on the subject of performance, the design document says only the following:
In a very frequently executed already-correct loop, the new allocations may be unnecessary and could potentially cause more garbage collector pressure and a measurable performance difference. If so, standard monitoring and allocation profiles (pprof –alloc_objects) should pinpoint the location easily, and the fix is trivial: declare the variable above the loop.
To be clear, I’m not against the change! I would just expect to see a much more rigorous analysis of the performance impact than this somewhat hand-wavey dismissal of the concern.
Insofar as this change does not affect existing code behaviourally, it should be trivial for a decent compiler to canonicalise and generate the same code as it always did. Insofar as it does affect behaviour, performance is irrelevant. I have no insight into the go compiler, but if it is unable to see through this, then fixing that sounds like a much higher priority.
There’s a pretty good general analysis of this as a PL design/implementation question, with discussion of what Javascript/Ruby/Python/C#/etc. each do, in a sidebar of the book Crafting Interpreters in the chapter on closures, “Design Note: Closing Over the Loop Variable”.
Amazing summary. Not surprising considering that Russ Cox mentioned Dart as a source of inspiration for those new semantics, and that Robert Nystrom, the book’s author, is working on Dart :)
This seems like a great change to address a very common Go pitfall.
The rationale for the current behavior of re-using the loop variable was always performance. The claim was that allocating a new value for each iteration of a loop was costly enough to out-weigh the various points of confusion that are described in the link. So I would expect that a proposal to change this behavior would include a pretty thorough analysis of the performance impact. But on the subject of performance, the design document says only the following:
To be clear, I’m not against the change! I would just expect to see a much more rigorous analysis of the performance impact than this somewhat hand-wavey dismissal of the concern.
Insofar as this change does not affect existing code behaviourally, it should be trivial for a decent compiler to canonicalise and generate the same code as it always did. Insofar as it does affect behaviour, performance is irrelevant. I have no insight into the go compiler, but if it is unable to see through this, then fixing that sounds like a much higher priority.
There’s a pretty good general analysis of this as a PL design/implementation question, with discussion of what Javascript/Ruby/Python/C#/etc. each do, in a sidebar of the book Crafting Interpreters in the chapter on closures, “Design Note: Closing Over the Loop Variable”.
Amazing summary. Not surprising considering that Russ Cox mentioned Dart as a source of inspiration for those new semantics, and that Robert Nystrom, the book’s author, is working on Dart :)
Very interesting. As someone who only occasionally writes Go code, I had no idea about this issue.
See also: https://go.googlesource.com/proposal/+/master/design/60078-loopvar.md