Baffled at this claim I searched and found one person who really seemed to be saying "if Go changes dramatically...".
This recurring notion that Go fans are anti-generic is not rooted in reality. Instead they simply didn't buy the "either it's there or the language is useless -- generics or bust!" argument that pops up in every Go discussion. It's a fine, if imperfect, language without generics. It's a better language with them.
How would you define "badly designed?" I can imagine a context where the "well designed" type system is very plain.
I suspect a lot of the generics hate is due to a large chunk of the community coming from dynamically typed languages. In which case they're just have a negative reaction to unfamiliarity.
It’s true genetics will shrink some specific APIs, where they are a good fit.
But they will also be used opportunistically by developers excited to push their boundaries.
Of course you can say “just don’t do that” which works if you have a tightly controlled codebase. But most code is not that, and will be handed off to novices over and over for fixes.
So, it’s a question of whether you cater to the advanced developer who can capably handle a vast toolset, or do you commit as a community to more rudimentary tools, in order to reap the rewards of systemic simplicity.
There is no right answer.
I believe in the future all languages will fork into a simpler novice subset for general use and an expansive language for infrastructure. These will both be valid in the same parser, but the subset will be quarantined at the package management level.
Go, EZ-Go, C, EZ-C, etc
I am writing all of my code in EZ-JS
At least it'll definitely get rarer.
That's not the case anymore. We have C++ which has generics and "fixed" C's lack of complexity for sure...Now for some 'weird' reasons some people still use C. Wonder why ?
In certain domains like UNIX like OSes, I don't see C ever going away, due to the infrastructure, symbiotic relation with the OS that gave it birth, and the culture.
This exactly. The beauty of Go is that currently you do not need a book called "Go, The Good Parts".
Yes, generics would make a lot of things easier, but almost everything more complex and footgunnish.
I don't think we'll see this happen much for existing languages, but it could be a very interesting angle for a newly-designed language (or rather pair of languages).
The focus moves towards a taxonomy of types and developers (myself included) sometimes get stuck on difficult type problems. There's something about trying to preserve type safety which sets the bar extremely high for bypassing the type system when there's not an easy solution and before you know it you've wasted 2 or 3 days writing code which doesn't actually do anything but placate the compiler.
And often that type-safe concoction you create is almost indecipherable when you come back to it later.
For example here's a project I worked on recently which cached a concrete version of a generated method using generics:
https://github.com/DataDog/dd-trace-dotnet/blob/develop/src/...
Used like this:
var originalMethod = DynamicMethodBuilder<Func<object, byte[][], object, object, bool, T>>
.GetOrCreateMethodCallDelegate(
redisNativeClient.GetType(),
"SendReceive",
methodGenericArguments: new[] { typeof(T) });
At least for me that was really hard to figure out how to do and I still have to squint to see what the heck its doing. The non-generic version wasn't type-safe and it wasn't as fast, but it sure was a lot easier to read and understand.And to give some sense of the complexity involved, Rob Pike mentioned in his talk that the proposal spec for adding generics to Go is longer than the spec for the entire language.
I think the complexity is worth it, but I just hope we can be cautious about how and where generics get used in real-world code, otherwise we'll end up with gobbledy-gook that only experts can decipher... and that would be really sad, because the promise of Go was a language normal engineers could be productive with.
They're not all the same though are they.
C++/CLI had both compile-time generics (templates) from C++, and run-time generics from the CLR. And they could be complementary at times.
For compile-time generics, Dlang are a lot more sane that C++, having had the benefit of coming later, and dumping C compatability.
Similarly, CLR (C#, ...) generics had the benefit of being designed having seen Java first, so IIRC they're baked into the CLR. CKR generics were derived from work done at MS Research Cambridge, and I seem to remember Don Syme (F# creator) being rather proud of them. Disclosure: I was contracting at MSR Cambridge back in 2007.
Anyway, the golang designers will be aware of these implementations, so hopefully they'll come up with a nice design.
I don't hate generics. I see the value of generics, especially after having worked with Go for so long; I've had to do some mental gymnastics to get around not having proper generic collections.
That being said, I'm not excited about seeing generics in other people's code. The added complexity doesn't really solve problems I have anymore.
That being said, I'm actually way less excited about overloading.
I think generics and function overloading is going to make me think "where the hell is this coming from?" a lot more often and then I'm going to need to load it up in my IDE, or vim with way too many plugins, and start following definitions.
This seems to be slowly changing, but Go was designed to be a solution to Google problems - python being slow but some c++ applications taking literal hours to compile. Keeping that perspective in mind makes it easier to understand why Go maintainers have not accepted an implementation of generics into the language yet.
Look up things like SFINAE and compile time metaprogramming. Templates were not intended for those things. When they work they're ok, but if they go wrong good luck following the 10 line error message.
Here's an example from Rust:
https://www.reddit.com/r/rust/comments/5nifpm/they_said_rust...
That's what people don't want.
Incautious use of the template mechanism - or just a minor typo - has given me couple screenfuls in the past.
But. There are many modern languages that already have generics. Why can't Go be that one that doesn't cave in and remains powerful in its niche and perhaps may never be the preferred tool in other areas? Why must it be useful for web development, microservices, DAL, etc.?
Any implementation of generics in Go will come with complexity tradeoffs.
I feel like the community learns more about languages and software engineering when we maintain language diversity and see the pros and cons of each approach in practice.
I want generics for selfish reasons, but would also like to see how a modern strongly-typed language solves problems without it.
It's great that they're trying out the process on smaller, more simple proposals. My hope is that this system will either produce really good features, or reveal that there are simply no satisfying solutions.
I still fell things are up in the air about exceptions but maybe we can just agree on generics which would make me feel better.
Using go without generics just felt insane to me...
Things like typeclasses or multimethods offer vastly more abstraction power. These are (a bit) more difficult to understand, but you certainly don't have to be a genius (take it from me). I can kind of get why a language targeted towards "average" programmers might want to omit these.
But here's the thing: The less abstraction power a language has, the more complexity must be handled by the developer. This leads to things like Java Spring, which you do have to be a genius to understand.
This is a fun example since you can do that in Go now, as it comes with a generic vector (essentially) and map :D
I think that was the design decision, 95% of generics use cases are covered by having growable arrays and maps, so why clutter the language with generics.
I like generics, I think most people who dislike them are coming from C++ templates, which has downsides that don't exist in newer generics systems (such as in C# or F#)
Generics allow for less code, thus they are easier to debug, test and reason about. I've used them a lot in C++ and I do miss them in Go. It's not a deal breaker for me either way, but for people who write larger, more complex code, not having them makes it more difficult (more code to write, test and maintain).
C does not have generics either. Go is a lot like C in this regard.
And no, being a dynamic language is not what makes Python slow. Lua, Nim and Scheme are all examples of dynamic languages with fast implementations.
- Yes, being a dynamic language slows it down a lot. For example, when evaluating a+b, the interpreter has to check the types of the variables a and b at runtime beform performing the right form of addition (it might be an int, or a string, you dont know). Even with JIT (just in time compilation) the compiler has to initially “guess” that the variables are numbers, and fall back if that is not the case. Statically typed languages do not have this problem, because you know the types of variables beforehand at compile time.
By the way, Nim is not a dynamic language. And LuaJIT is one of the the fastest dynamic language implementations because the language is very simplistic (compared to Javascript/Python/Ruby) and Mike Pall is a robot from the future...
That's not necessarily true. In Scheme, a very dynamic language, the compiler will generally make choices about memory layout of the various values before launching into the evaluation phase. Where safe or possible to do so, it will probably reduce the number of choices that will have to be made at runtime, at compile time. The interpreter may not have to lookup what the data type is, because it may just have two bits of memory and an instruction to call. You can know what the data will be, and optimise for it. [0]
There's no reason that: b = 1; c = 2; a = a + b needs to be slower than a = 1 + 2 if b and c are never referenced before or after. But in Python, it is, because the design makes it harder to know whether or not an object should get optimised away.
> And LuaJIT is one of the the fastest dynamic language implementations because the language is very simplistic
Right, Lua is dynamic, and one of the design choices was making it simple, and so it's easier to make it faster.
[0] https://www.youtube.com/watch?v=2Op3QLzMgSY&list=PLE18841CAB...
[1] https://www.amazon.com/Structure-Interpretation-Computer-Pro...
Some of it is simple stuff, like CPython being interpreted, so PyPy get's a huge boost by JITting.
Some of it is much harder stuff, like the way Python is designed to store objects in memory (a list is a pointer to a contiguous space of pointers to things that might be pointers...), and everything that hangs off each object (everything has a dict), and the awful GIL ([0]). Awful for performance, great for thread-safety.
Every single part of a language design has trade-offs. It depends on what you're trying to do whether or not they help you, or hinder you.
Sometimes you change how you're doing things because priorities change, and get a radical improvement, like Python's 3.6 Dict. Most of the time, you don't. One step at a time. Not being able to break backwards compatibility hinders the designer, if they realise a trade-off they've made was a mistake. So you get stuck with some features you'd rather not have.
To be sure, the internal implementation of CPython (the only one I'm familiar with) is complicated as hell. But it's a whole lot simpler than any fast JavaScript runtime I've ever used. I think that's the result of a conscious choice by the maintainers/BDFL/community in Python, not a side effect of it having less funding (assuming that's the case).
This could be my naïveté, but I don’t see why generics in Go couldn’t work analogously to the way they do in TypeScript, just a way for the compiler to verify the correctness of code accessing an interface{}.
Without generics, if you need a list filled with TPS Reports you basically have 2 choices:
- Use the 'untyped' List that deals with objects. You will have to cast to TPS whenever you look up an item and you will have to make sure that no one accidentally adds a Timesheet to this list.
- Write a custom TpsReportList. I'm sure you'll be able to write an implementation as efficient as the language creators. Oh an if you copy and past from TimesheetList, don't forget to check all names. `tpsReports.AddTimesheet()` is just embarrassing.
With generics, you will have a `List<T>` type. If you need a list of TPS Reports you will use the type `List<TpsReport>`. If you need a list of Timesheets, you will use `List<Timesheet>`.
You can't add the wrong type of item to such a list, you will always get the declared item from that list and you can't assign an instance of one type to a variable of the other type.
As for all the folks claiming they'll leave Go if it gets generics, it's faintly reminiscent of Mac fanboys claiming PowerPC chips were the Very Best right up until this was obviously not true. C++ generics are a PITA in many ways, but you can be insanely productive in the STL without having to hand-roll everything and with good type safety.
Despite the pain, I've been amazed at how easily you can build up some really complex data structures as pretty much one-liners ("Oh, I need a vector of maps from a pair of Foo to a set of Bar") that would either take a preposterous amount of code (or be a type-unsafe disaster waiting to happen) without generics.
Hopefully the final Go 2 generics proposal will capture some of this goodness without some of the horrifying C++ issues (error messages, bloat, sheer brain-numbing complexity).