I agree though with your initial reaction to Go and generics- it seems strange to argue not to include generics due to complexity when the alternative is either type assertions from interface{} types, code generation through some sort of [preprocessor](https://github.com/cheekybits/genny), or copy-pasting code. All of these are more complex than a simple generics implementaton! Golang could even include some sort of generics less complex than Java since it wouldn't have to worry about co vs contra variant types, and Java's generics aren't that hard to work with.
I will. Generics in Java are a net loss in my opinion. They provide marginal static safety, no additional dynamic safety, no performance benefits, and lead to substantially more complex APIs. I'd have been happier if they were never added. I would prefer a Go-like type-assertion construct or an analogous "occurrence typing" feature.
C#, on the other hand, has a sensible generics implementation that provides meaningful utility thanks to value types. However, I am not ashamed to admit that, in the absence of value types, I'll resort to Whatever<Object> plus some casts without a second thought if I find myself doing even the slightest bit of work to satisfy the compiler.
Besides, the introduction of generics has added a tremendous amount of safety to what used to be typecast littered Java code pre 1.5.
> the introduction of generics has added a tremendous amount of safety
It's added marginal _static_ safety. It added no dynamic safety. Static safety is welcome, but frequently not worth the lengths people go to achieve it. Hence my comment about instantiating generic types with Object in the event that the cost outweighs the safety.
> to what used to be typecast littered Java code pre 1.5
Occurrence typing would dramatically minimize the syntactic overhead to casting. There have been research variations of Java that accomplished this: instanceof checks insert implicit casts on branches where the instanceof check is true. Similar extensions have been explored for collections to further omit the instanceof checks without requiring explicit type parameterization. For example, if a collection is only written to privately, you can infer casts from what types are inserted in to the collection. This can achieve the same safety without massive complexity increases to sub-typing, static dispatch, reflection, type signatures, etc.
By the way, Go already has this. If you have a variable, say `foo`, with a generic type, say `interface{}`, you can say
switch foo := foo.(type) {
case MyFirstConcreteType:
//foo is a MyFirstConcreteType instance here
case MySecondConcreteType:
//foo is a MySecondConcreteType instance here
default:
//foo is still the generic type here
}
See https://golang.org/doc/effective_go.html#type_switch for details.This could be exactly what Go needs. Any link to some reference material on this topic?
Fyi...the Google style guide doesn't ban generics/templates. It's discouraging the "template metaprogramming" which is a technique beyond parameterized types (generics) ... e.g. using recursion in Turing Complete template programming to calculate compile-time values.
If we're talking about just generics, here's example code from Google Inc's sparsehash: https://github.com/sparsehash/sparsehash/tree/master/src/spa...
It uses generic type parameters. If you ask the author if the library would have been easier and "less complex" to write if generics language feature were removed from C++, I think we'd be certain the author would say "no."
Even without asking the author, if anyone believes the library is suffers "simplicity debt" because it uses generics, they can fork the code, rewrite it, and then prove to skeptics that the hashing library was much clearer and more maintainable without generics.
Go isn't against generics, they are open to discussion about adding them if right approach to implement them without adding much of extra complexity would be found. Generics do add complexity, it is bearable in most cases, especially given the benefits, but it still exists.
Authors don't want to end up with something that C++ has, where you have to manually limit yourself in order for your code to not be too complex and unmaintainable, at the same moment, adding templates just to have them won't add any immediate benefit of large magnitude.
Well, your response was to grasleya and he wrote: "Why is it that relatively simple and ubiquitous language features like [...] generics are [...] an unacceptable amount of complexity?" [...] Are there any Java, C++, etc. developers arguing for the removal of these features [...]?"
And your reply was: "Yes, google c++ style guide recommends to avoid [...] template metaprogramming,"
... and therefore, that makes it look like you're conflating "generics" with "template metaprogramming".
If your intention was to respond with a random tidbit unrelated to the proposed generics for Go, it means you're just introducing a non-sequitur and confusing readers trying to reasonably follow the context of the thread. The op (grasleya) wasn't talking about "template metaprogramming" to compare to "generics" in Go.
Turns out you can handling error like go in c++, or I should say go just used the proven working way of error handling in google c++.
Complex templates are just a type of complexity, like any complexity, avoiding them is always the right thing to do.
edit: missed a word
Go allows a wide range of complex metaprogramming through reflection, struct tags, ... to say that Go is void of that kind of garbage is lying.
Go also has a bunch of weird rules regarding type conversion and assertion, its type system isn't covariant... Go has its share of problems, so much that go maintainers themselves keep on introducing type unsafe API in their own std lib. Go has a type system problem, period.
Finally all platforms supported by Go aren't first class. Windows doesn't support Go plugins or Go shared libs AFAIK for instance.
Yet, code in Go tends to be easy to read, uniform, very well suited to work on in a team. No megabytes size of code style is required, in most cases there would be no problem to understand code written by other person because of how simple the language is.
This was not my experience working on a moderately sized Go codebase. In fact, it was one of the messiest agglomerations I've ever had the displeasure of working with (and I worked at Twitter when it was still a monorail). Everyday code that is simple in most other languages was a drawn-out mess in Go. The type system was an obstacle to be worked around. Metaprogramming (via go generate) was a joke.
That's just my experience. Others' may differ.
Or if you showed a few examples of "code that is simple in most other languages was a drawn-out mess in Go" or how Go's "type system was an obstacle to be worked around" when compared to type system of other mainstream languages like C++/Java/C#.
As it stands, you're in a minority. The consensus is that Go codebases are among the most readable.
Your statement is as unsubstantiated as his. But at least the parent doesn't feel as arrogant claiming he represents the majority. Go doesn't magically makes code more readable than any other language. It's just something some gophers like to think since they often start projects from scratch.
Among who--other gonuts/gonads/gophers? In my neck of the woods a Go application over a few thousand lines is already a yellow flag and a Go application, period, requires defending the choice over TypeScript or Java. (Difference being, of course, I'm not holding up my experiences as objective.)
As far as whether go makes it easier or harder to make easy to manage code bases I don't know that it matters one way or another. I've written bad code in other languages and go. I will say, I've never seen a large go code base, and I suspect if I did it would suffer very much from things that people complain about with the go language.
The situation is not really benefit vs. limitations. The style guide is put as general guide. It's a proven way of writing code inside google that most people agree and think is acceptable.
It's about taking a common ground on how to use a language, rather than finding a sweet spot of trading-off. Benefit vs limitations is part of the equation, but it's put in a context that only makes sense inside Google.
Therefore it's not self-evident that the benefit vs limitation argument automatically applies to general use cases outside of Google.
Or, I do not like people use Google or any other large organization's approach to automatically prove that those rules makes sense in different settings.
They also seem to admit that if they were to do it over again and start from scratch they'd use exceptions:
> Things would probably be different if we had to do it all over again from scratch.
It seems that thinking on exceptions in low-level languages is firmly in the "no way" camp.
Contrary to popular thinking, exceptions are not free.
For example, when Chrome disabled rtti and C++ exceptions in Chrome codebase, it resulted in saving 6MB (20%) of code. See https://bugs.chromium.org/p/chromium/issues/detail?id=19094
This is when exceptions where not actually used in the code. The bloat is merely from enabling C++ compiler flags to generate rtti and exception support code.
Except Go isn't particularly close to the metal anyway. The only way Go is low level is in the same way Java is low level: it's very limited in terms of the programmer's ability to create abstractions.
Technically speaking, Rust does have exceptions with its unwinding feature. The panic! macro throws an exception, and catch_panic allows you to catch it. It is implemented exactly the same way as C++ exceptions, with the accompanying code bloat and performance pessimization, and you have to think about exception safety exactly the same way when writing unsafe code.
Because they made a mistake by not including them?
More seriously, you are approaching the argument the wrong way. You don't judge a feature by how popular it is but by analyzing objectively whether the presence or absence of that feature leads to higher quality code
Actually most of them have them.
Just out of my mind, Mesa/Cedar, Ada, Modula-2, Modula-2+, Modula-3, D, Object Pascal.
If they were really needed, then you'd have significant numbers of people trying Go and then leaving because it isn't expressive enough.
Not that that doesn't happen, but we're seeing the language gain mindshare as more people appreciate the simplicity, partly due to not having these features.
So, generics and exceptions would improve go. It just wouldn't be go anymore.
I assumed that was what the term "Simplicity Debt" was referring to.
No, but I'll bet money that there are Java, C++, etc. developers who have abandoned those languages for Go. Developers often vote with their feet before trying to change a standard.
I will say that there is some good post compiler tooling around making sure that error handling isn't skipped but its definitely a weakness of the language.
Source: Former Java dev
Turn the argument around. Are there any Java, C++, etc. developers arguing for the removal of these features from their languages? Are there people who say that even though these languages have generics you shouldn't touch them because they're bad? Do any devs with option/maybe types really want to go back to unsafe code that can fail if you forget to check for nil/null? Show me someone who hasn't drunk the go kool-aid who still makes these sorts of arguments and I might actually start listening.