So in these discussion you have devops-type people mainly dealing with APIs that are perfectly content. And the ones that work with algorithms are talking past them because they don't experience the same pain.
Instead of changing the language to enable generics everywhere, maybe there is a lighter version that exists that only applies to numerical problems. Is it possible that a boxed "Number" type would solve most of the problems?
I find that an ideal set of tools allow us to describe our task and write our code using the same idioms.
The fact that "mapping JSON" doesn't actually involve calling "map" on JSON data is a great example of why not having generics in golang is frustrating for me.
Mapping functionally it worth it if the transformation between A and B is regular enough. But things are dirty. Some irregularities appear and now the perfect higher-order function doesn't work nicely anymore. With the imperative approach it just means adding 1 -3 more lines.
I also see this with graphics people who live and breathe small (2x2, 3x3, and 4x4) matrices don't care about "type level integers" (as Rust calls them) to make 6x9 matrices efficiently live on the stack or in an array.
> Is it possible that a boxed "Number" type would solve most of the problems?
If you mean it the way I think you do, not for me. I can easily afford to fit a billion 4 byte floats in memory, but I can't afford a billion 8 byte box pointers to a 4 byte box with an n-byte tag, and the cache locality could be horrible.
However, if Go had an elegant macro system (Rust's doesn't seem too bad), I could get by though.
It also doesn't really work in Java either because you have to use the Object types.
Even in rust this looks pretty complicated: https://travisf.net/rust-generic-numbers
Maybe it's easy in c++?
I've seem a similar comment made on almost every discussion of this issue... are folks just not aware of the limitations with generic implementations?
Btw, it's "ironic" that you think pointing at two broken implementations says anything about where it works. "Are folks just not aware" it's ridiculous to be snarky when arguing from a position of ignorance?
But most other data structures? Nope. Too much of the algorithm depends on the primitive type.
And that makes generics a nice boon for computer scientists and certain library authors, but of middling benefit for day-to-day coding. If the container works, you can copy-paste-modify your way to the types you want, or automate the same in a macro or code generator. It's not beautiful but it doesn't have to be.
Generators are a legitimate solution and I wish they'd get more love.
It's so sad to see people pushing to radically alter a language that they will probably never use because it will never be suitable for their needs.
My biggest complaint about Go is the lack of generics; I bet they're just trying to get more adoption. That being said, adding generics won't eliminate all the other things I dislike about the language.
What's "so sad" is you think this Reddit style "Don't use it" imperative is an acceptable way to talk to people. You're rightfully afraid of complexity creeping into an otherwise clean language, but it would suck less if you said it better.
I won't argue with you my use of the imperative mood as I'm not a native speaker. I'll take note of it.
Developers love to be able to write their magical code and their clever abstractions and often forget that their code is paying the price by becoming less clear and less readable. From a security perspective that's a huge loss.
I know that people with the right security mindset will do the right thing, and have more code where it improves clarity, or have slower code when it makes it easier to understand what is being done. But unfortunately that's a tiny minority of developers.
Are you saying that it has to be that way with generics? Because I would disagree with that. Cautiously applied, generics can make your code more clear, more readable and, most importantly, more type safe – and not just because of containers, see Swift’s key paths for an example.
Clearly, that justifies the fact that you can't sort an array of doubles and an array of floats with the same function.
Certainly I've seen my share of bizarre C++ template shenanigans (bad) but I've also been able to reuse other people's really well written container classes rather than roll my own, all with strong type safety (good).
Everyone will make their own decisions about generics. Personally I find the risk of "bad generics magic" to be more tolerable than "endless shitty workarounds for not having generics".
I don't particularly care which direction Go goes in, and don't write a lot of it myself, but I'm very curious what the alternative is.
I'm fine with Go having a handful of built-in generic containers+functions. In fact, I think most people asking for "generics" would have their true needs met by adding a few more built-ins to the language. I pursued that idea here: https://github.com/lukechampine/ply
I sympathize with the programmers who really do need generics and would like to program in Go, because I love the language. But the way I see it, 95%+ of programs don't truly need generics. I like the trade-off Go makes by omitting generics, and it makes me sad that the language could change in such a radical way to meet the needs of that <5%. A language doesn't need to be perfect (or even usable) for everyone! Throwing in feature after feature to satisfy everyone just creates a culture of compromise and destroys a language's character. I want a set of narrow tools that I can master. No one ever complained that a hammer makes a terrible paintbrush. So in a broader sense I think this whole discussion reflects a wider need for good languages. We need ten languages of Go's caliber! I know the "just use a different language" argument is kinda callous, but the alternative feels worse.
I don't have any opinions on adding generics to Go because I don't have a sense of how it interacts w/ other features of the language, but having to specialize all your types to specific uses means there are very common types of libraries that are significantly harder to find in Go than in other languages, or are much less useful, or work around the lack of generics w/ interface{} casts and are significantly less type safe. I suspect that people who deny the value of generics enjoy learning about the implementation of these things and writing them themselves rather than using libraries. Don't get me wrong, there's value in that, but it's at the expense of writing libraries with stable interfaces, boilerplate-free code, large systems that can easily be refactored, etc.
It also makes it harder to actually use a type system for the value it provides: the ability to encode facts about data irregardless of their provenance. Libraries may provide interfaces that work on a certain number of presumed useful primitive types, but your own types can encode far more constraints. Without the ability to use those types you will have to care about provenance again (has this value been validated for use by this function?) or constantly reuse a normalization process to construct those values, which may introduce conversion overhead and creates more error-prone situations. Not to mention that generics also provide constraints about what a piece of code _cannot_ do. The example made famous by haskell programmers is that an "fmap" function defined as such cannot tamper with the values being mapped over, since it has no knowledge of their concrete implementation:
fmap :: Functor f => (a -> b) -> f a -> f b
Genuinely, I don't understand why you would create a static type system in a new language that didn't allow for parametric polymorphism, it's one of the most fundamentally useful features in type-checking code.
Yes, they do. Pretty much 100% of programmers in statically-typed language need to use generic types/functions.
The "95%+" thing is just an observation that one typically needs to define type-parametrized structures of function very seldom. This is true, but it's in no way a good point against adding generics, because those remaining ~5% of cases are crucial for peaceful programming the other ~95% of times. That's why Go has built-in generic types, but as it's adoption grows, it's becomming clear they won't do any more...
> In fact, I think most people asking for "generics" would have their true needs met by adding a few more built-ins to the language.
You argued against magic and now you'd like to add some more of it to the language...
Only snag, minor enough, is that emacs auto-indent becomes confused by the double braces, as in "{{.templateVar}}".
Right, because the alternative to higher-order abstractions is spending much of your time completing MadLibs-style implementation templates for solutions to solved problems instead of just including the library that contains the (higher-order) solution and focussing on solving the new part of the your problem.
Programmers thought of ever edge case, until you found that edge case that wasn’t covered in the long chain of inheritance of generics.
Point being, I agree with you, I know Go doesn’t have inheritance like C# but I’m pretty sure we, as a community, we’ll find a way to complicate everything Go related.
Not really.
> You can't chain together operators in point-free style, or add a property to every 'Object', or directly increment a string, or anything like that. In other words, it's a terrible language for code golfing. But that sort of code has no place in a production environment anyway.
Complete straw man.
That's a weird thing to say seeing that Go very much is magical... Slices/arrays are magical and so are maps, channels and channel operators, the make() function and a whole bunch of other features.
I think your understanding is filpped. Generics are not a way to add magic, they remove magic. That's the whole point. Unfortunatelly, that which one doesn't understand may seem like magic to them even though it's not.
For example, compare a channel implementation in Go and Rust. In Go, the whole thing is pretty much magic. In Rust, it's just another struct that the compiler treats in no special way. Getting familiar with the magic of Go channels is only good for working with Go channels, the knowledge is not applicable for any other part of the language nor other languages. Learning generics on the other hand gives you better understanding of numerous features in multiple languages.
Programmers love generics because they enable higher-order abstractions, and programmers love abstractions -- code that isn't DRY is like an itch we need to scratch. Programmers also hate special cases, because they feel restrictive and inconsistent: I recall quite a few people protesting that Go's 'range' keyword shouldn't be restricted to a handful of built-in types, but rather should support any type implementing an Iterator interface.
But Go was not designed to be perfectly consistent or to enable high-order abstractions. It just aims to be productive at scale, and that often means restricting the programmer. Go tries to be non-magical, and sadly that can take much of the whimsy out of programming. You can't chain together operators in point-free style, or add a property to every 'Object', or directly increment a string, or anything like that. In other words, it's a terrible language for code golfing. But that sort of code has no place in a production environment anyway. It's "clever" code that gives the programmer a little dopamine hit when he writes it, and his co-workers a headache three months later. Those are misaligned incentives.
So I worry about generics because they let you abstract with wild abandon. They let you inject a little magic. And I fear that programmers will be seduced by their love of magic, and I'll be the one who ends up paying the price.