2 ms·
For some odd reason, Go still doesn't have parametric types (they call it generics), yet it seems to have remained surprisingly sane despite supporting generic
by fxtentacle 6y ago
For some odd reason, Go still doesn't have parametric types (they call it generics), yet it seems to have remained surprisingly sane despite supporting generic interfaces.
https://golangnews.org/2020/11/experimenting-with-go-type-parameters-generics-in-goland/ https://golangnews.org/2020/11/experimenting-with-go-type-pa...
Do you have any idea what they did right that Java lacked?
- rmetzler 6y agoMy guess it’s the different idea of what an interface is and how errors are signaled. An interface in Go can be defined by the client code and types just need to implement the functions. In Java Interfaces need to be defined before any code can use it. And exception handling makes code hard to reason about because it introduces hidden control flow. I think Generics don’t give you that much leverage. Without them you need to duplicate the code for each type or class, but duplicated code is much easier to work with. Yes, it’s not really dry, but copy paste and search/replace is something which increases developer productivity, fixing bugs in code with too many generics decreases it. And one thing to keep in mind: historically a lot of interfaces in Java were necessary because Java had no lambdas. In Go functions are first class citizens and you don’t need an Interface just to dynamically call different functions.
- megameter 6y agoThe appeal of generics is in writing data structure libraries that are primarily abstract containers. With parametric typing you can bind the contained type early, rather then being bound through runtime indirections and checks like a dynamic type system, handles to another container, interface compatibility, or other such tricks. That's an important role, especially in performance-sensitive domains, but outside of that, it never seems to work very well, which makes it a easily misused feature in every language I've used that offers it. Go's original design basically took the form of offering this for the built-in structures but not letting you roll your own, ushering you towards interfaces if you really needed it, and because Go makes interfaces convenient, it mostly works.
- fxtentacle 6y agoI agree, the native array and dictionary support in go makes it easy to forget that they don't have generics. BTW, as an example of generics abuse, crypto++ comes to mind. It's such a huge pile of templates referencing each other and exceptions being used to control the command flow, that I was once hired as a freelancer just to link the whole thing into a static library, because the company using it was unwilling to deal with the source code, but needed it for FIPS compliance. It's an incredible engineering feat that they managed to let you mix and match cryptographic functions and containers and storage formats as you see fit, but having a C++ stack trace with 5 abstract templates in it makes it very painful to debug if stuff goes wrong.
- fxtentacle 6y agoThanks for pointing out lambdas. I hadn't considered them, but I wholeheartedly agree :) My go projects tend to have small helper lambdas and lots of defer calls, which are effectively lambdas, too. Without them, I'd need a lot more source code and/or an IDisposable interface for pretty much every io class.
- apta 6y agogolang is basically Java pre-generics. Working with large golang codebases is quite annoying and error prone, partly due to the lack of generics. They didn't get it right at all.
- fxtentacle 6y agoHaving built an offline-capable distributed database in go, I noticed that even "larger" projects in go tend to be a lot less source code than building something similar in Java. And maybe that's just my personal style, but to me defer is much more important than generics. I can't even remember how often I've had to debug Java bugs where someone forgot to close a ResultSet for an SQL query... And then you leak memory so badly that restarting tomcat with a daily cron is still not enough :( With defer, you can expect people to write the cleanup code immediately after opening something, which makes it much easier to confirm that you're not leaking resources.
- apta 6y agoJava already solved this with try-with-resources, which the linter or IDE can warn you about (because the instance has to inherit from `AutoCloseable`). Not so with golang's defer, where it is much more likely that the developer can forget to call it.