Actually it surprises me we're still inventing languages where local variables can be mutated, which seems to be at the root of the problem here
Actually it surprises me we're still inventing languages where local variables can be mutated, which seems to be at the root of the problem here
We've known about the problem for a long time. I have notes from the run up to Go 1 (circa 2011) where we considered making this change, but it didn't seem like a huge problem, and we were concerned about breaking old code, so on balance it didn't seem worth it.
Two things moved the needle on this particular change:
1. A few years ago David Chase took the time to make the change in the compiler and inventory what it broke in a large code base (Google's, but any code base would have worked for that purpose). Seeing that real-world data made it clear that the problem was more serious than we realized and needed to be addressed. That is, it made clear that the positive side of the balance was heavier than we thought it was back in 2011.
2. The design of Go modules added a go version line, which we can key the change off. That completely avoids breaking any old code. That zeroed out the negative side of the balance.
As for validating your software, the answer is the same as its always been… tests, tests and more tests.
Huh? Where’s the list? From the top of my head I think this is the only thing that repeatedly bit me, although I’m very aware of the behavior of for loop scoping. Linters save me nowadays at least.
Are there other things like that in the language that deserve a fix? Maybe things to do with json un/marshaling?
One weird thing that always goofed me up was that slices are passed by value but maps by reference. Always made it confusing how to pass them for serialization/deserialization. The compiler didn't complain it just panicked. Seemed like something the type system should catch.
type noCopy struct{}
func (*noCopy) Lock() {}
func (*noCopy) Unlock() {}I'd much rather have a crash than silently corrupting output.
Local mutability is probably one of the most common uses of mutability. A lot of it is using local state to build up a more complicated structure, and then getting rid of that state. Getting rid of that use-case is just giving up performance.
They aren't local, but belong to the outer scope. The misconception in a nutshell.