Hacker News new | past | comments | ask | show | jobs | submit login

This is too similar to interfaces for me and seems like it would only add to the complexity of the language, documentation, and compile time for a small increase in generic code.

One of Go's core strengths is simplicity. I've personally witnessed both C and Python programmers jump right into Go projects with minimal assistance. Learning new packages is absurdly easy because the code is so simple and documentation practically generates itself. I worry that widespread use of this feature would negatively impact the language in that regard.

Lacking a true "generics" feature has had an influence that people tend to overlook, which is that the Go community is less reliant on dependencies. One of Go's proverbs is "A little copying is better than a little dependency" [0]. The ecosystem is better documented and healthier because of it, avoiding the require("left-pad") world of the dependency abyss.

The language lends itself to being used for smaller, more concise code bases where things are written with specific and narrowly-defined purpose. It implicitly discourages "Architecture Astronauts" [1] and that strength shouldn't be overlooked or sacrificed for a few new container options.

[0] https://go-proverbs.github.io/

[1] https://www.joelonsoftware.com/2001/04/21/dont-let-architect...




Missing generics certainly had some influence on golang, but not sure I understand your point. How does adding generics lead to a reliance on dependencies, or the absence of generics reduce reliance on dependencies?

The relative lack of "dependency hell" in golang compared to other languages is because of the great standard library. Golang also never had an official/proper (imo) solution for package management until just this past year or so (although people worked around that a bit)


I think the argument is that generic code, being, well, generic, promotes reuse at an abstract level, rather than a concrete level. Abstract code can be more difficult to understand than specialized code that does only what is needed in a particular use case.

I like the generics proposal, but it seems like a valid concern.


To clarify further, I think the concern is that people will start adding dependencies for things that could be implemented concretely in a dozen lines or so, e.g., a generic slice.Map function or even a linked list.

Note that this comment is not advocating for or against this proposal or generics in general; it just took me a few re-reads to understand the concern and I hope to save others some time. :)


I hope that if this design is accepted they would also include some common generic types/algorithms in the standard library instead of leaving it to a 3rd party. For example an updated sync.Map (that doesn't use interface{}), some things from SliceTricks [1], or maybe the Set example (although I don't really have a problem with map[thing]struct{}, Set is arguably more clear).

IMO I think having a standard library that judiciously used generics would be almost pure upside for most Go programs. Being able to do math.Sin(x) instead of float32(math.Sin(float32(x))) just seems like an improvement in every way.

[1] https://github.com/golang/go/wiki/SliceTricks


Agreed. I think this would go a long way toward addressing the original concern.


That's exactly what needs to happen. We will never arrive at a more powerful platform by self-gratification and refusing to stand on each others' shoulders. One well-tested reusable implementation is dramatically better than a hundred incompatible bespoke ones that happen to work and a hundred more that are subtly broken.


They're saying they think every project duplicating code that could be a shared generic dependency is actually a virtue.


>One of Go's core strengths is simplicity.

I also remember reading some one said their Software has increased complexity due to Go's Simplicity. ( Or something similar along the line )

It really is a balancing act. And it seems there is no one size fit all solution.


> Software has increased complexity due to Go's Simplicity.

Which way are you meaning this. The way I read it was that because GO was simple, we were able to build more complex systems. But you seemed to indicate that was a bad thing?

Yes making complex that can be made simple is the way you want to do things, but some things simply are not simple, and thus require complex software.


No, that the simplicity of the language forces complexity in the code written in it.


I have thought about this for about a day, and I can't agree with you.

Every time I have seen complex GO code and investigated how it got that way it was simply the result of one of the following. 1) Writing GO code before fully understanding the language. 2) Trying to write GO code like it was some other language.

I have seen some crazy complex GO in my days, and after spending hours and hours of trying to figure out what the code was doing -- I have always been able to simplify the program to a nice concise bit of code -- and I can assure you there are much better programmers out there than me.

Often the complexity is people trying to implement generics in some crazy round about way, or have prioritized dependency injection, or code coverage test to a extreme.

My favorite example of this is https://github.com/rdadbhawala/dutdip -- and here is a good talk on it https://www.youtube.com/watch?v=HBLJV0cPRBM

The code base that implemented this in production is an amazing mess, I can assure you of that.


For example check Kubernetes talk from FOSDEM.


That's not been my experience of Go. Complexity is contagious - if your language is complex your code tends to be complex. Go's language design intentionally avoids complexity and Go code is some of the most readable code I've ever seen.


"Complexity is contagious - if your language is complex your code tends to be complex."

Going from assembly language to Go (increasing language complexity) decreases code complexity.

Stated a different way, would removing a feature from Go (say Goroutines) necessarily make a Go codebase simpler? If so, then I have to question why they added it in the first place.

Maybe your statement could be defended given enough context and caveats, but the overall relationship between language and code complexity is clearly more... complex... than you imply.


In general, I have a lot of sympathy for your concern--I've used Go and other languages with generics, and the difference is noteworthy. I personally think generics is worthwhile on balance, but I respect that others don't share this opinion. I'm glad you brought it up because most conversations about generics outside of the Go community pretend as though there is no tradeoff at all. That said, what sort of generics proposal would be sufficiently powerful (or perhaps that's not what you meant by "different from interfaces"?) to alleviate your concern? And note that this proposal is quite a lot more powerful than interfaces because interfaces aren't generic over multiple types, while contracts are.


Left-pad had nothing to do with dependencies being bad and everything to do with the fact that you could delete dependencies from NPM.

I predicted at the time that people would take away the wrong conclusion—"dependencies are bad"—from the left-pad incident. Sadly that prediction seems to have come true.


I don't really see how that's an unfair conclusion to draw.

The more dependencies you have, the more likely you are to get one that's going to cause a problem down the line, be it due to conflicts with other libraries, subtle bugs that take years to manifest, or someone deleting something from upstream package manager (as was the case with left-pad).


"Subtle bugs that takes years to manifest" are way more likely to occur with code you write yourself because you didn't want to import someone's production-hardened code than with popular dependencies.

Take crypto code. Which do you trust: a homebrew implementation of AES-GCM because nobody wanted to add a dependency, or libsodium?


I feel like crypto is an outlier; you should definitely use well-vetted libraries for that for a whole plethora of reasons.

However, I think the reason that people got upset over the left-pad thing was because it was a library that most engineers could write fairly easily, without adding in another failure point.

If you rely on the the language/platform's built-in libraries, typically the amount of wheel-reinventing you are doing boils down to writing simple wrappers, without adding in another external point of failure. These libraries are typically more production-hardened than something you'd find on NPM or Maven or Nuget.


Or take leftpad. The point is there is a spectrum along which the cost/reward calculation varies. Absolutely don't roll your own crypto and absolutely roll your own leftpad. Maybe this is a bad conclusion, but I think it's important to address that not all dependencies are crypto, at any rate.


Another example is internationalization. Most of the reason why software is bad for people who don't use non-Latin text is that people keep writing homebrew text code instead of using dependencies. This has ugly cultural implications, and it's entirely because of the "copying is better than dependencies" philosophy.


> Or take leftpad.

Leftpad was a problem with a particular package management system, not with code reuse. It's true that avoiding code reuse is a way to avoid package management problems, but it's kind of like the way decapitation is a way of avoiding mental health problems.


As pcwalton already said, the problem with left-pad was with npm and not the concept or the usage of dependencies per se.


This thread is debating that premise. Your argument is ultimately circular: “the problem with leftpad was npm because the problem with leftpad is npm”. pcwalton may well be correct (we often disagree and frustratingly he’s probably right more often than me) but not because of this circular argument.


It isn't as simple as being the wrong (or the right) conclusion. It needs to be seen in context. In the context of who is saying it, in the context you understand it and in terms of what actual code we're talking about.

What I mainly took away from the left-pad incident was that if people will add dependencies for code that is so simple that it takes less than a minute to write(1), then what else will they add dependencies for? I was a bit surprised at the sheer poor engineering judgement involved in adding massive amounts of dependencies so carelessly when they were so fragile as they proved to be in NPM.

Raise your hands those who check all dependencies before every release? Did you look at all the change logs? Did you check for issues, security vulnerabilities, or that it may be time to upgrade to a newer version (or not)? Did you follow all the transitive dependencies and do the same? Do you routinely evaluate each dependency with an eye to replacing it? No? Yes?

Using known good implementations that you know to be maintained, is good. Overdoing creates new problems. Making a culture of it creates a community of fragile, ratty code.

Dependencies are bad if you overdo them because with scale problems tend to morph into new kinds of problems.

(1) You usually do not need to do all of what left-pad does. Usually you need one specific case. And once you have done it a few times (for a few different cases), it becomes like a kata you can write in seconds. It is much faster than adding a dependency. Not least because adding a dependency actually means you should spend enough time reviewing the dependency - in depth the first time, and perhaps just checking the change logs or commit logs on subsequent versions.


If all else is equal, then additional dependencies are a bad thing. Otherwise the only reason to not depend on everything would be code size... And if it's a compiled language with even just a minimum of optimizations then even that wouldn't be an issue.

As with most things - it is a trade-off.


That’s a very slippery slope argument that could apply to almost anything. Fortunately, most people realise the benefits of generics - and it has nothing to do with dependency management (which is already a mess by the way).

I’m more worried about eccentricities in the implementation that we’ll get out of the golang team. Then again, maybe we’ll be pleasantly surprised.


I agree with your position, but you’ve missed the point. Everyone recognizes the benefits of genetics; the debate is about whether they’re worth the cost. Not everyone can even bring themselves to admit there are costs.


Agreed. What I don’t get is why people try to change Go all time instead of simply using different languages for different problems. If you absolutely need generics in a project, there are a ton of languages out there that will fit your bill.


This proposal is by one of the core Go maintainers, and the others have never come out against generics just expressed their concerns about how to implement them in Go while maintaining compile and execution speed. It's a bit over the top to suggest that they quit using Go just because you disagree with them.

I primarily program in Go. While I think often HN makes too big a deal of Go's support for generic types currently being (more or less) limited to slices, maps, and channels (those go pretty far for a lot of programs, especially when combined with interfaces), I don't get the passionate anti-generics attitude this post seems to have attracted either. I'm wary of architecture astronauts just like everyone else, but I think at least the Go team could probably use generics judiciously in the standard library in way that would benefit most programs (like using sync.Map without casting to interface{}, or doing math on float32 without needing to do float32(math.Sin(float32(x))), etc).


Yeah, for me Go is a specialized tool mostly for dealing with IO. The entire standard library and all of the builtin types are really designed for IO-centric applications which is why it's a natural fit for servers/microservices. Small, narrowly defined applications that mostly coordinate via sockets and serialization and it does those things really well.

In those worlds you're more likely to move data between logical units in JSON or Protobufs (both of which Go is good for) than to need proper generics so I don't understand the push from this subset of the community.

As far as container types and data structures, look at the number of well built storage solutions that don't seem encumbered by the lack of generics at all like: boltdb, bleve, BadgerDB, InfluxDB, etc.


Generics help with reducing of code duplication. This doesn't really depend on what you want to do exactly, more on how complex your code base is.


Microservices? I'm sorry but what do you mean? Don't you use business logic in your microservice or you just do I/O without actually doing something with the input? Generics is for that part.


What I really like about Go is the consistency of their tooling. gofmt, godoc, the GOPATH convention, single binary deployments. I like all of that.

Maybe we could port some of those ideas to other languages so that Go programmers will feel at home :)


Static compiling, common across all OSes before it became an option alongside dynamic linking.

Fast compile times, already being enjoyed by many with Turbo Pascal for MS-DOS, or Object Pascal for Mac OS, among other languages with similar support for modules.

Godoc, javadoc did it first.

Gofmt, indent was one of the first and every IDE has done it since ages.

Other languages already have those ideas.


I'm sympathetic to many anti-generics positions, but this argument is lazy.

You rarely know all of your requirements up front, and walking back a language change a year or more into your project is almost always prohibitively expensive. At that point, you find yourself with a handful of equally-bad language-hybridization options. One of Go's objectives is scalability--as Go projects mature, they should not find themselves boxed in by the language. In the case of generics specifically, you have a slightly better option than language hybridization or changing languages outright which is generating generic code, but that's only slightly better (because now you need code generation built into your CI/CD pipeline which is inherently worse than a naive generic type system implementation and it also imposes a high cost on all clients of your generic code, since they will also have to adopt your same generic build system as the standard Go toolchain isn't your-generic-build-system-aware).


Sometimes we don't get to choose project requirements, nor the projects.


That’s not the language’s fault, nor is it a reason to downscale what makes it great.


It is, because its designers created a language in 21st century while ignoring what has been done since 1976.

The generics proposal hints that the design is reminiscent from Ada generics. Well its first standard was released in 1983.


Maybe because they're working in companies that has "one language to rule them all" approach, and that language happens to be Go?


My guess is because they didn't choose the language. Many businesses prescribe the language(s) they use.


It will take a language deciding to remove generics before I believe this is anything but stubbornness.


... but you can't remove major features while retaining compatibility. So for the most part you can only add stuff.

So, people switch to new simpler languages. The way you remove things from a language is to create a new one.

Then these new simpler languages become popular, and then people want their critical favorite bit added. And eventually the language is no longer simpler. And people switch to another new language, and the cycle repeats.

Because we couldn't convince people to just use the existing complex language if they want that. Because, really, this is all a struggle to influence other developers. These days it's not enough to work the way that is best for you, you need to find ways to harness a critical mass of other developers, and at the same time contain the mess and damage that a huge number of miscellaneous developers out in the world can do to your ecosystem.

It kinda sucks. Where possible, I like to use older, less popular, more minimal: libraries, frameworks, tools.


Lots of languages have breaking changes between major versions.


Is it lack of generics that has resulted in fewer dependencies, or the incredibly full featured stdlib?


a bit of both?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: