> MRVs mostly end up being worse tuples
I think you noticed yourself that you’re getting too hung up on terminology. Multiple return values are a half-hearted, non-reified version of tuples.
Acronym for Multiple Return Values https://gobyexample.com/multiple-return-values
It's a plus versus minus type of situation, where both have their advantages and disadvantages, along with a number of workarounds and alternatives that can be used.
In many cases, people can return arrays, hash maps, or structs in place of tuples. That looks like the reasoning in Go, where if the person needs something beyond MRV, they can use the other options available. Go and various other languages, didn't need or didn't want to lean on tuples as much.
The problem is that Go only has the drawbacks of MRV and leverages essentially none of the advantages.
> Go and various other languages, didn't need or didn't want to lean on tuples as much.
As far as I’m concerned go would be a strictly better language if it had tuples (or even just the ability to unpack structs).
All the nonsense about foo/foo2 to handle both single and multiple results would go away, and pretty much the only thing which would be lost is individual addressing of MRVs for named return values, which is easy enough to replace by naming the return struct and going through it.
MRV, go does not have tuples.
Go is not the only language with MRV (as a special case) and they’re not necessarily bad, iirc Common Lisp uses them as auxiliary data channels and has a whole host of functions to manipulate and refit them.
Go is singularly incompetent at MRVs though, in the sense that only syntax and builtin functions get access to variable arity (e.g. if you access a map entry you can either get one return which is a value, or two which are the value and whether the key is/was in the map). So MRVs mostly end up being worse tuples infecting everything (e.g. iterators needing Iter and Iter2 because you can’t just yield tuples to for loops).