3 ms·
> ... No hidden magic ... This has been changed since Go 1.22. Go 1.22 introduced magical hidden code: https://go101.org/blog/2024-03-01-for-loop-semantic-chan
by tapirl 2y ago
> ... No hidden magic ...
This has been changed since Go 1.22.
Go 1.22 introduced magical hidden code: https://go101.org/blog/2024-03-01-for-loop-semantic-changes-in-go-1.22.html https://go101.org/blog/2024-03-01-for-loop-semantic-changes-...
- ithkuil 2y agoIs it magic? The reason they changed the behaviour is because the previous behaviour was surprising and thus "magical". The new behaviour is more consistent with what you think about what is a scope of a variable. The fact that a compiler has to add some code to instantiate a variable is not magical. Otherwise all what compilers do would be magical
- tapirl 2y agoI never doubt it is a good change for "for-range" loops. The change for "for-range" loops didn't introduce magic hidden code. But the change on "for;;" loops creates more surprises than before and gets rare and tiny benefit. It introduced magic hidden code. Please read that article for what is the magic hidden code and the surprising cases.
- ithkuil 2y agoyeah I see; that said if for;; behaved differently than for range it would cause a different set of surprises, so I guess consistency was deemed more important.
- tapirl 2y agoThe cost of making the consistency is too large and the benefit is too tiny.
- ithkuil 2y agoThe surprise factor is only for the current generation of people who are used to it and who are used to other languages that the same kind of for loop and closures that can escape (basically only JS?) But the internal consistency between the for;; and for range allows you never doubt about the rule again once you first learned it. Yes, there is the risk that you'll get it wrong once (if you first learn the language or if you are used to the old rules) but if the language authors had only fixed for range, then a lot more people would get for;; wrong just because they would be never sure which way it would be. So the only "solution" would be to never fix "for range" or disallow for :=;; ? In any case I think that if you really care about the old semantics, it's not a bad idea to making it obvious to the reader that you intend to directly or indirectly take a reference to the iteration variable and that it effectively survives the loop body with: var i int for i = 0; i < 4; i++ {
- tapirl 2y agoThe core problem here is that "Go promotes explicitness" ended at Go 1.21. Since Go 1.22, it is no longer valid. The change of "for-range" loops is good is because no implicit code is introduced. And the change of "for;;" loops is bad is because implicit code is introduced. Implicitness often causes surprises. The implicit line pa_last, pb_last, pc_last = &a, &b, &c in the new semantics is absolutely an evil. And the seriousness of this problem is that, if you upgrade your go version in go.mod files, the behavior of the your old code might change. And the change might be not always easily found in time. > but if the language authors had only fixed for range, then a lot more people would get for;; wrong just because they would be never sure which way it would be. This is just a problem in theory, it is never proven (and now no chance to prove it). > So the only "solution" would be to never fix "for range" or disallow for :=;; ? I think it is just fine to only make changes on "for-range" loops, just as C# have done. The assumed problem of "for;;" loops is never proven, or just proven to be tiny. IMHO, it is just rsc's personal willing to make the change. This might be the worst decision made in Go history.
- foldr 2y agoAs the sibling says, this is just a semantic change in the scope behaviour of loop variables. You need to add an extra line of code to emulate Go 1.22 semantics in Go 1.21 code, but there's not really any hidden magic if you just interpret Go 1.22 code according to its own defined semantics.
- tapirl 2y agoI know that, the change of "for-range" is good. But it creates more surprises in the uses of "for;;" loops. Please read the cases in that article.
- foldr 2y agoIt's a change in semantics. So it's surprising if you don't know about the change, and not surprising if you do know about it. I'm familiar with the kind of code that behaves differently under the new scoping rules. Looking at the examples in the post, I don't really share the intuition that the behavior is any more or less surprising for classic 'for' loops as opposed to 'for...range' loops.
- tapirl 2y agoIf you can guarantee that every gophers know the effects of the change. :D The problem of the change is that, if you upgrade your go version in go.mod files, the behavior of the your old code might change. And the change might be not easily found in time. I indeed haven't found any surprising cases caused by the change of "for-range".