Neither Python nor Java programmers have to do that.
If Go is annoying with how little power it provides, that's fair, but other type systems can be just as annoying then, because when given the ability to, type astronauts will blast off into space, purely as a matter of honor or instinct.
Besides, code generation isn't all that bad. Java programmers will eventually find some kind of code generation in their build setup (serialization/schema tools).
It is the number one thing that makes C++ templates unusable: semantics defined by means of code generation.
We've been here before with the C preprocessor. There's nothing wrong with having a preprocessor, but in C it is necessary to use the preprocessor and that causes a lot of problems, like making it especially difficult to write tools.
In a hypothetical world where the designers never added the specific containers they did, you'd get a whole lot more value out of generics for containers. But it turns out, the designers used what seems on the surface like a kludge to get most of the benefits, while saving most of the cost. It's a perfect embodiment of the kinds of tradeoffs I'm talking about.
Architecture astronauting can be prevented with best practices and code review, not with language limitations. It’s a fools errand to try, code generation allows you to get all the complexity and more of generics.
Which is not the argument made by anyone. Indeed, I explicitly acknowledge that there is a certain fraction of use-cases not covered by the builtins. So there isn't really any disagreement about this.
The question is how large this fraction is, how much it would benefit and how inconvenient/costly the existing workarounds are. Like all engineering questions, these are impossible to talk about when dealing in absolutes. And once you actually talk about these questions quantitatively, I achieved the goal I had with the post - to change the debate into a quantitative one explicitly acknowledging the tradeoffs involved.
> Architecture astronauting can be prevented with best practices and code review, not with language limitations.
I work at a company which has probably one of the highest standards in regards to code review in the industry. As such, I disagree with you that it is effective in addressing this.
> It’s a fools errand to try, code generation allows you to get all the complexity and more of generics.
If that's the case, where do the complaints come from about the lack of generics? It seems that Go really has generics then, in your opinion?
Of course, that's a strawman and a misrepresentation of your argument. But what makes this a strawman, the difference between the existing workarounds and actual generics, is just as effective an argument for your side as it is one for my side. Because codegen is made so inconvenient, people bias heavily towards using the builtins, away from custom data structures, if they can at all get away with it. Thus greatly reducing the overall complexity of the codebase.
So it would seem to me, that this argument is logically flawed. Either codegen is a poor replacement, thus leading to people using less generic code, thus there is an effective reduction in complexity. Or codegen has the same effect on complexity, which would mean it is used just as much, meaning it can't be that bad a workaround.
I don’t agree that using piles of built in objects makes the code easier to understand. If I want a Tree<Node, Node, Value>, how is using lists of lists and integer pairs making my code easier to reason about? Or using code generation to make reams of classes that create a Tree for everything I want, and anyone who uses my functions? How is encouraging either of those things a positive?