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

Go doesn't let you build abstractions - it offers what it does, and if its not enough - tough luck.

What I dislike worst is the denial of the Go community and creators, claiming that generics are too complex and that you don't really need them.

I dismissed Go not because of its lack of abstraction power, but because its authors and community is incapable of admitting problems when they see them. A similar problem with CoffeeScript (conflation of declaration and assignment + scope rules) and the authors' refusal to admit that there is a problem also made me dismiss it entirely.

Every language/platform has problems. But not every language is in denial of them. We should all avoid those that refuse to acknowledge their problems - because that points to a much deeper, much more serious problem - a problem that cannot be eradicated with technical means.




> I dismissed Go not because of its lack of abstraction power, but because its authors and community is incapable of admitting problems when they see them.

For what it's worth, I have had a similar experience.

One time I expressed a personal opinion on G+ about something I don't like about Go personally. A Go fan re-shared this in the Go community and it turned into a debate. https://plus.google.com/+RalphCorderoy/posts/ZfaM1a21tyW

People argued that my concern was theoretical and would not happen in practice.

Then, by chance, someone wrote a totally unrelated blog article about their actual experiences writing Go. The article was overall positive about Go, but among their list of dislikes from using it in practice was exactly the concern I had voiced.

I posted this to the thread and the response I got was: "When I read that, he didn't give an example of it coming up. Again, it seems purely hypothetical."

Apparently a person writing about their experiences who says "There are a few things about Go that I'm not super happy about, and that tend to bite me from time to time," and then talking about problem X, is not enough evidence that X actually happens.

I took from this experience that, at the very least, there is a strong bias against admitting problems.


I'll just leave these here: https://groups.google.com/forum/#!msg/golang-dev/ZTD1qtpruA8...

https://github.com/clipperhouse/gen

I'm sorry you got the impression of that there is a strong bias against admitting problems. I haven't seen that bias at all myself. Instead I've seen a willingness to look at different approaches to the problem and an unwillingness to compromise the other design goals of the language.


TBH, neither of those solve the same problem generics / parametric polymorphism were created to solve: being able to abstract over types when writing a function or data structure.

The first link deals with automatically generating things like printers or comparison functions. Its orthogonal to type abstraction - for example, in Haskell you would use "deriving" or TemplateHaskell macros to do the same thing. This kind of code generation is useful for creating monomorphic functions that depend on the structure of a type (for example, a comparison function for that type) but it won't help you latter create polymorphic functions that work on any type (for example, a sorting function that receives that comparison function as a parameter).

The second link suffers from a similar problem. The only types that can be used generically are the ones defined together with a "//gen" comment and you also can't define your own generic functions (for example, a SumOfDistinct function that composes Sum and Distinct)

You are giving me the impression that people are trying to solve Go's generics problem with tooling when its actually a language design and type system problem.


> You are giving me the impression that people are trying to solve Go's generics problem with tooling when its actually a language design and type system problem.

Go community lives in 1993, back when C++ compilers shipped with code generation tools (mostly macro based) and templates only existed in CFront.


> I'll just leave these here

Are these links in relation to generics? Generics weren't the issue I had been posting about.

> Instead I've seen a willingness to look at different approaches to the problem and an unwillingness to compromise the other design goals of the language.

For what it's worth, if the people responding to me had said "yes, what you say is a potential downside of our approach, but we think that the advantages of our approach outweigh the disadvantages," that would have been fine. There would have been no need to debate anything further.

The reason the argument went on is because the Go advocates were dismissing the possibility that my concern had any validity whatsoever.


> https://groups.google.com/forum/#!msg/golang-dev/ZTD1qtpruA8...

Everything in there listed as impractical in Go is possible in D without external tool, with just regular meta-programming:

- generating parsers from grammar https://github.com/PhilippeSigaud/Pegged

- embedding files as array of bytes:

    ubyte[] = import("file.jpeg");
- protobuf files at compile-time: https://github.com/msoucy/dproto

- generating tables at compile-time with CTFE

Instead of copying what works the Go leaders pretend it doesn't work.


The fact that it's not necessary to explicitly state which interfaces are implemented by a type is a key design decision in Go. It's not going to change.

Every language decision has pluses and minuses. I think most Go programmers feel that this problem is fairly hypothetical because it doesn't seem to come up for most people in real code. But, you're right, it's possible for it to come up. Every language decision has minuses, including this one.

But the pluses outweigh the minuses, so this is not going to change. Sorry.


But FAQ clearly states that generics are open issue. Something changed?


> What I dislike worst is the denial of the Go community and creators, claiming that generics are too complex and that you don't really need them.

That's not the claim. The claim is that generics add complexity to the language and its ecosystem. That, I'd hope, should be an undisputed claim.

Go's lack of generics is a design tradeoff. The occasional piece of awkward code is worth the overall reduction of complexity at an environmental level.

The Go creators do not deny that generics would make things easier. In particular, concurrency is one area where some kind of parametric type system would be really helpful. But we, and many others, are finding Go to be a great tool for a wide variety of jobs. It has won developer mindshare specifically because of our focus on simplicity. It doesn't seem worth compromising that to reduce the occasional bit of repetitive code.


> The claim is that generics add complexity to the language and its ecosystem. That, I'd hope, should be an undisputed claim.

I strongly dispute/oppose that claim.

1) Generics don't add any complexity to the rest of the language. If you don'y use generics, you're back to the "plain Go". Especially since generics doesn't mean just "ML-style polymorphism"; I'm pretty sure that many people would be happy with a very limited implementation of generics, e.g. only for reference/pointer types (or even only for interfaces), with all types/generic arguments declared, not inferred. In that case, implementing generics would only require a change of the type-checker of the language, or in the case of Go, not even that, which brings me to the second point:

2) Generics are already implemented in Go (the compiler/the language/the libraries), via map/arrays/slices, it's just not accessible to user code. I really can't see how anybody could make an honest claim that "Go is avoiding generics because of added compiler complexity", when that complexity is already there.


The answer to the question "where should complexity go?" is always "as low as possible". Complexity at higher levels interacts with more code and begets more complexity. The lack of generics or macros is complexity that is forced on the end user which could be handled by the compiler (language devs).


Implementation complexity is not the issue.

The issue is that a programmer needs to understand how the generics model works and how it interacts with every other feature of the language. That makes the language more complicated, which (as you say) leaks into the higher levels.

Generics is just one of many features that Go could have, but does not because it makes the language bigger.


Simple languages shift complexity to the programmer's shoulders.


Writing more code is not the same as more complexity. Irritating, perhaps, but not more complexity. A larger language overhead to keep in mind is more complexity.


More code is more complexity from a maintenance point of view. You have to maintain n copies of the same code, specialised to n types. Find a bug in one, hopefully you'll remember to correct it for all n.


So if I have a larger language overhead to keep in mind, that's more complexity, but if I have a larger codebase overhead to keep in mind, that's not more complexity? You're trying to have it both ways, IMO.


That depends on the addition of code obtained by limitation of features in a language. If the additional code base is so severe, that it increases the complexity significantly, I'd argue you have chosen the wrong language for the job.

Of course, a codebase in it and of it self can be complex, regardless of language (and even if the language is well suited for the job), but I am only talking in the context of when features (or lack thereof) in a language increases the codebase complexity.

But a few more lines in the same function to do the same thing as a single line in another language, is not more complexity, that's just more lines. It's not like the lines now are somewhere obscure or in another function.


> That depends on the addition of code obtained by limitation of features in a language. If the additional code base is so severe, that it increases the complexity significantly, I'd argue you have chosen the wrong language for the job.

Agreed.

> Of course, a codebase in it and of it self can be complex, regardless of language (and even if the language is well suited for the job), but I am only talking in the context of when features (or lack thereof) in a language increases the codebase complexity.

Agreed.

> But a few more lines in the same function to do the same thing as a single line in another language, is not more complexity, that's just more lines. It's not like the lines now are somewhere obscure or in another function.

And here's where we begin to disagree.

I delete redundant comments in code, even if they're correct.

This is significantly more effort than leaving them alone: I have to recognize they're redundant, check VCS history to ensure I'm not missing something, create a changelist, request a code review for the changelist, wait for the reviewer to verify I indeed didn't missing something, submit the changelist, verify the changelist still builds (you never know when you'll hit a bizarre compiler bug, corrupted file, conflict resolution related typo), merge the changelist back to the mainline...

This is a significant amount of work! But I feel it's justified: they're increasing the complexity involved with reading the code. The more pointless redundant comments I'm reading, the less important things I can remember, and the more likely I am to skim over something important such as a bug.

This is not additional cyclomatic complexity in the codebase. Structurally, the complexity of the fundamental operations my program performs haven't changed - I haven't touched anything that should affect the final executable output in any meaningful form at all. But I'm still making it simpler* to read.

(* a synonym of simple to note: noncomplex!)

In non-comment code, the problem is much worse. More code means more opportunities for typos, more code which must be read to grok the actual execution of the code. If you thought bugs got missed when I was skimming past the comments, well let me tell you, it's way worse when I start skimming past the code! And this happens to everyone.

There are still a few people who don't mind writing all their programs in straight up assembly. Sure, it's a bit more code, but all the if and while conditionals from C aren't reducing the cyclomatic complexity of their programs either compared to structured programming with conditional jumps. They say there's more important things to worry about than pure line count - and they're entirely correct. They're writing codebases in assembly that I'd find much more readable than some of the codebases I've read in much much higher level languages.

But having addressed the more important stuff I'd still like to address the less important stuff. It eventually adds up, and I've seen it make me more productive. (This has encouraged me to try many different languages... so far not Go, I've yet to come up with a problem which makes it the right language for the job.)


I think that the "complexity" cost of generics is overstated, really. Can you explain how generics make user code more complex?


They refer to the complexity of the compiler and language, not to user code complexity. Any given language has a complexity budget and they wish to expend it elsewhere.

(Note that I am in disagreement - I do think generics should be added).


That's a weird stance. If there are complexities that programmers face that can be absorbed by a compiler, it must be, because that would pay off for every programmer , in every project, in every bug prevented.


> If there are complexities that programmers face that can be absorbed by a compiler, it must be

Not sure. If absorbing it would make the compiler much slower, much more complex, or the compiled code less deterministic, or corner cases in the compiler much more numerous, I think it may be reasonable to not go this path.

It looks like the go compiler in itself is a nice piece of engineering, like a F1 race car. And a bunch of guys say they want it with automatic gears. Proposing an automatic version would change too many things in the internals, and the result would be another kind of cars.


> If absorbing it would make the compiler much slower, much more complex, or the compiled code less deterministic, or corner cases in the compiler much more numerous, I think it may be reasonable to not go this path.

Why would that be the case for Generics?

I think nobody says "Go needs Generics, but the implementation needs to be horrible."


In the Go FAQ [1], when they list the purpose of the project, the first answer they give isn't about concurrency (as some might suspect), it's:

  "It is possible to compile a large Go program in a few seconds on a single computer."
They've been consistent about this. It's a major design goal and, for some, compilation speed is worth more than support for Generics.

[1] http://golang.org/doc/faq#What_is_the_purpose_of_the_project


Any language with modules and generics and production quality native code compiler, does enjoy fast compilation speed.

It is a good sell when the audience only knows about C++ compilation issues.


Last time people were ecstatic about go compilation speed, the speeds cited didn't even hold up well against gcc.. The go compiler is not very fast, but as you point out the features of the Go language makes it amenable to fast compilation.

What kills compilation performance for larger C/C++ projects is include hell and managing build dependencies, which as you point out is mitigated in language with modules.


And with luck, even C++ will finally have modules. Still need to wait a few more years, though.


And yet, the dmd compiler for D support templates and is faster than the gc Go compiler.


I'll say it again: Go doesn't have generics because of implementation complexity. The tradeoff was against the additional complexity that our users would have to deal with.


I don't know where people would have gotten that idea from: https://golang.org/doc/faq#generics


right, because a big codebase to deal with the lack of generics doesnt add complexity at all.

you see, the problem with the complexity of a language isnt real. it is perfectly possible to avoid generics in c++ forever. but there will come a day when you think to yourself, was it really worth it to be this lazy? then you take a peek and (assuming you understand generics by then enough to use it a little) suddenly half of what you have writen so far is for the bin.


I was only addressing the comment of the parent that suggested adding parametric polymorphism would kill compiler performance.


DMD isn't faster than the go compiler anymore


You've said this several times. I believe you, but can you please link to your source? There aren't a lot of comparative compile time statistics out there. Last time I checked, dmd was quite fast regardless--maybe no longer faster than the Go compiler, but within the same ballpark.


No, that is not what I was referring to. It is definitely user code complexity that turns us away from generics.

People tie themselves in knots with generics all the time. Just look at pretty much any mature C++, Java, Scala, etc codebase.


As somebody using pre-generics Java libraries from time to time, I can say with confidence that generics are not the cause of complexity. Casting from Object is a source of bad type safety and doesn't help with documentation. The complexity you'll find in a mature codebase is a function of the way it is architectured and the complexity inherent to the domain, mostly.


I wish people wouldn't assume there's only two options - Generics or casting from Object/interface{}/void* It's a straw man argument. No experienced Go programmers are trying to say that's a good way to write code. The idea is to restructure your code so that basic data structures and interfaces pick up the majority of your reuse scenarios.


I'm no Go programmers, but I relatively often need to take a parametrized basic data structure as storage and write a parametrize class on top of it, while hiding the data structure because it's irrelevant.

Well, I guess I'll keep not being a Go programmer :)


I'd say people tie themselves in inheritance and interface knots more often than generics knots. Especially invariant generics are rather hard to get wrong - they place such constraints on the types that most operations are unavailable.


> People tie themselves in knots with generics all the time. Just look at pretty much any mature C++, Java, Scala, etc codebase.

That's not my experience at all. Generics are generally not a source of pain. Do you have any specific examples of your claim?


People tie themselves in knots with classes/packages/interfaces/concurrency/computer code all the time. Just look at pretty much any mature codebase at all.


I think trade-offs have been made already. If they bring in "generics" they would have to back-pedal and now many in the community would have to in a way refute their previous excuses of why they didn't need generics. ("But I have been arguing on public forums for the last 2 years that generics are not useful, what do you mean we'll now implement generics....")

There is also a chance that it will slow down compilation and or runtime. Java, C++ and other code compiles slower. Is it because those languages are stupid and slow and made by idiots? Not necessarily, it is because they have more features. Many added later (with added complexity of keeping backwards compatibility). The fear I think, is if Go gains those new features, its compilation and/or execution speed or claims of simplicity will not hold any more.


You have it all backwards. We didn't build Go in order to have arguments on a mailing list. And I don't think the people saying "I don't need generics," are lying. I think they actually believe what they say, and I'm sure if we did introduce generics today many of them would say "I think this is a mistake."

Yes, the tradeoffs have been made. The language has been designed. It is very unlikely that Go 1.x will see generics.

Yes, any new language feature may slow down the compilers and/or runtime. Go values compilation and execution speed highly very highly. To include any new language feature we would assess whether it is worth the various costs; that much is obvious.

But there are technical reasons why C++ and Java could never compile as fast as Go, and they have nothing to do with generics. Go's dependency model is the main reason it can build fast.

And simplicity is a core tenet of the language design. To sacrifice that would be to admit defeat entirely. We could have just been using C++ all along.


> And simplicity is a core tenet of the language design. To sacrifice that would be to admit defeat entirely. We could have just been using C++ all along.

Well that was my point it. Turning Go into something like Java or C++ will make it not Go any more.

> We didn't build Go in order to have arguments on a mailing list.

Not sure many popular languages were built for that. But arguments on mailing lists is what you get. Quite often the smarter people are, the better they are able to veil things like disappointments, personal dislikes, and others in technical arguments. I have seen it in private meetings and public discussion forums. The inertia of defending something vigorously and then having to back-pedals is unpleasant.


Simple is the biggest weasel word in programming.

In practice it's pretty much a measure of the temperature of bear porridge that a given person currently finds just right.


C++ currently compiles slowly due to lack of modules.

Eiffel, Ada, D, Modula-3, Active Oberon, FreePascal, Delphi... enjoy fast native code compilers and do have generics.


Lack of generics != lack of abstractions.

The Go community freely acknowledges that generics are a nice feature, and that lacking them is a pain point of Go sometimes. Although many Go developers will tell you that sometimes turns out to be not that often in reality, which has also been my experience.

Rob Pike has outlined the tradeoffs inherent with generics here: http://research.swtch.com/2009/12/generic-dilemma.html

The bottom line is it's not a feature that comes for free, and if most of the time you don't really need it, maybe the costs aren't worth it. That's a bold statement for a programming language these days, since generics is a central feature of every popular, modern, statically typed language. Whether they are right or wrong I won't attempt to say. The language may well get generics one day, but it's early days still and the team is rightly focusing on more important features for the moment.


That really depends on what you mean by "most of the time". After all, you only write a generics based library once, and you reuse it many times - therefore on the outside it appears that you don't really use generics all that much.

In my opinion, depriving a "normal" language user of generics is like depriving a Lisp user of macros. Whatever it is, its definitely not just "bold".


I've done most of my Go programming on library code. A sync library for relational databases to sqlite (for mobile devices) and an embedded database. Lack of generics has bothered me a little, but copy and paste with a multiple-cursor editor really makes short work of it. I think the worst part is really our natural aversion to code duplication and the ugliness of it. e.g. having to write min/max for integers is pretty ugly (although not as ugly as converting your ints to float64 and using the stdlib min/max.) However, I spent more time thinking that it was ugly than writing min and max. Sure it's ugly, but programming is not art, it's engineering, and Go is a language for engineers.


> I think the worst part is really our natural aversion to code duplication and the ugliness of it. e.g. having to write min/max for integers is pretty ugly

Sometimes ugliness is a sign that something is designed incorrectly, especially if the language aids in making that more visually evident.

> (although not as ugly as converting your ints to float64 and using the stdlib min/max.)

Not to mention incorrect.

> it's ugly, but programming is not art, it's engineering

Not mutually exclusive. A good language would make incorrect or inefficient code "ugly" or "uglier" than correct code.

> and Go is a language for engineers.

So are languages with generics like C++, Java, Rust, Haskell, etc.


Plus all those dynamically typed languages which are intrinsically built on the concept of generics (JavaScript, Perl, PHP, Python, Ruby). /sarcasm Nobody uses them because nobody needs generics.


They are intrinsically built atop generics. Duck typing is row polymorphism. Dynamic languages often depend upon that flexibility to operate—and they enable it by allowing everything. Static languages without polymorphism are at a low point in that trade-off space since they restrict useful operations and provide no way to express the invariances needed to recover that flexibility.


I never thought people will actually come up and defend code duplication. It's definitely more than ugliness. The need to fix all the copies when they need to be updated is a bigger problem.


Or the fact that I actually saw someone on the mailing list also implement min() incorrectly due to copy-paste :)

> I never thought people will actually come up and defend code duplication.

Indeed. Some of the responses by some Go fans really leave me surprised to say the least.


It was the community attitude towards generics and code distribution that eventually made me focus on Rust and D.

At least those communities embrace modern computing abstractions and code distribution practices.


It's fine that you don't agree with our tastes, but it would be nice if you could stop coming into every Go thread and being condescending about it.

Like PostgreSQL and OpenBSD, I've been permanently turned off Rust because I never want to be left at the mercy of a community that invests so much time in harassing and insulting others.


We have rules against harassing and insulting others in the Rust community, and pjmlp does not speak for us.


Look, we gotta keep busy while waiting for the rustc build to finish. :(


Please tell me where you've been harrassed and insulted by the Postgres community? Sometimes people come into the IRC channel and say something that doesn't make sense and are told it doesn't make sense, and sometimes those people get very upset, but I wouldn't classify that as harrassment. And that's basically the strongest reaction you'll ever get from anyone in the community.


Any active comments thread related to MySQL attracts a derailing holier-than-thou invasion telling us how dumb we are for not using PostgreSQL. PostgreSQL's advocates haven't quite reached the arrogance level of Oracle DBAs, granted, but they're a lot more active.

I basically stopped using (public) IRC somewhere around 2000. I have little idea what goes on in PostgreSQL's IRC channel(s). I expect it's toxic, but I'd expect that for any project's IRC presence. Public IRC is an inherently toxic medium.


That doesn't sound like anyone I know of who actually works on PostgreSQL, and certainly not anyone I'd consider part of the PostgreSQL "community." The mailing lists, IRC channel and other forms of community communication are much more hostile to Oracle than any other RDBMS, and anyone who tries to start a flamewar there (particularly one about MySQL) is instantly shut down. I'm really sorry that you've been turned off from great technology by the actions of some overzealous Postgres users.


Except, I also talk good about Go in what concerns using it to replace C, specially in possible uses for real systems programming in a GC enabled language.

After all, when compared with the first Oberon version, Go only needs a few more primitives in runtime and unsafe, Kernel and SYSTEM in Oberon respectively.

This is what attracted me to the language in first place.


even if I think it's horribly naive if not flat out erroneous, I can see how someone could feel that way about OpenBSD...but Postgres?!

who is harassing or insulting anyone in the Postgres world?!?!


Yeah, the deficiency isn't the most harmful part - its the attitudes that come with defending that deficiency.


    > I never thought people will actually come up and defend   
    > code duplication.
DRY is a principle, not an axiom.

Overapplication of DRY as axiomatic has led to much pain and suffering.


Agreed! But what this means is that when you decide not to apply DRY, you need to have a reasonable justification. Code duplication in general is a bad thing.


Now you are shifting to a editing dilemma. Code duplication is not machine code duplication which is what really matters at execution time. Reading is also easier (even for non-Go programmers at least familiar with C) without templating-like syntax.


Machine code duplication is spending a few extra megabytes on perfectly valid, if duplicate, machine code.

Source code duplication is a risk of spending an hour, or maybe a day, of developer's time to detect the duplication, change it in concert in several places, with an occasional need of detecting and fixing a subtle discrepancy between the copies.

RAM is $0.015 per megabyte. Developer time is $50 per hour.


You could also spend that developer time trying to untangle code reuse between various components, or the more subtle breakages caused by changes that don't account for the expectations of all callers. Code reuse is still a tradeoff.


It should be noted that generic code is harder to break. It is, by definition, less entangled with its callers. There are also fewer operations you can do with generic parameters, so there are fewer ways to screw up.


Code duplication is definitely a programmer problem, not a machine problem. It's also a major problem. Code duplication increases the probability of programming errors, and makes maintenance harder. Any modern language with poor tools for keeping duplication at bay is suspect.


"My editor makes it really easy to do this terrible thing, so it's okay!"

I'm sorry, I quite enjoy many aspects of Go - but the argument that committing one of the cardinal sins of programming is okay because your editor makes it easy is worse than the actual language shortcoming itself.


Code duplication is not a cardinal sin of programming. In fact, the attitude that it _is_ has probably done more harm to [modern] programming than duplication ever did :)


This comment wins the thread!

Sorry, I meant to say that the language's shortcomings, even if temporary, start to attract a wrong attitude, which is sad (and you, golang team, should feel sad).


OffTopic: This sync library is available?


Correct me if I'm wrong but doesn't the current state of affairs (using Interface{}) have all the downsides of Java's boxing but without any of the type safety?


It reminds me of the wonderful fun days of Java 1.2 - anybody remember how proud Sun was of how everything derived from object so you could use the untyped containers for everything?


The main difference with casting to Object is that you can use type switches or safe casts which return an additional success boolean, to restore type safety quickly after taking the item out of its container. Yes, you can type-test in Java before you type-cast, but it isn't idiomatic, and it isn't syntax.


"It's fine in Go to do the wrong thing, because they added syntax to make it even easier to do the wrong thing."


The answer is not that you should use an empty interface, the answer is not to write generic functions.


Which leads to writing the same code repeatedly--because trying to wedge in reusability via insufficiently expressive structural typing is entertaining but often fruitless--and making the user wonder why they didn't just use something modern (setting aside stuff like Scala, even C++ can do channels, and past that the reasons for Go start vanishing real quick).


I write go 40 hours a week and have been for over a year. There's been only a couple times I wanted generics and those are structures I haven't actually needed to reuse yet. I'm not guessing about not being generics much.

Edit That being said, go is not for all projects. Some projects need a lot of generics. Don't use go for that.


Um, I've written Go. Nontrivial amounts, as it happens. In doing so, I recognized that I was regularly forced to write worse code in the pursuit of doing things idiomatically because I lacked the semantic richness of C++, let alone Scala. And this worse-is-better attitude of the Go community gives me a dim view of its future--and between its junk GC and its completely pedestrian semantic and syntactic propositions I already had a dim view of its present.

If you write reusable, future-facing code, generic types without the erasure of interface upcasting is required. There are no two ways around it.


It sounds like you were forced to write/maintain some Go code and are basing your opinion on that, an opinion heavily colored by the quality of the original code and your annoyance at your employer for making you work in something other than your preferred language(s).

It's even possible the software you were tasked with writing/maintaining was a bad fit for Go. I tried to mention that in my previous response. Such things certainly exist, and most Go enthusiasts will be more than willing to admit it.

However, saying you can't write reusable, future-facing code without generics is preposterous. To refute you, all I have to do is point you at the Go standard library. A huge body of code whose purpose is purely reuse, and not a generic to be found.

Or perhaps we could look at the thousands of reusable go packages found on godoc.org.

You don't like Go. That's a perfectly acceptable stance to take. But I don't think you've really given it a fair shake, either.


> If you write reusable, future-facing code, generic types without the erasure of interface upcasting is required.

You're entitled to your opinions, but this is a patently false statement. There is plenty of C code currently running on my machine that was written decades ago and is still actively maintained.

> And this worse-is-better attitude of the Go community gives me a dim view of its future

The Go community actively embraces Worse-Is-Better. If your opinions are well formed enough that you know you want nothing to do with it, then what is your point exactly? Yeah, you hate Go because you hate Worst-Is-Better. So what?


> You're entitled to your opinions, but this is a patently false statement. There is plenty of C code currently running on my machine that was written decades ago and is still actively maintained.

You're right. Sorry. You can do it by enacting a fair approximation of stapling your eyelids to your hairline. I apologize for not being exhaustive.

> The Go community actively embraces Worse-Is-Better. If your opinions are well formed enough that you know you want nothing to do with it, then what is your point exactly?

That I've had more than one long night dealing with an inherited Go application and it sucks and its developers should feel bad.

(OK, the last is mostly facetious. If they can't be bothered to use modern tooling, though, they should be tasked with maintaining their own crap...)


I think the real point is that Go just isn't a language meant for developers:

It's a language meant for sys admins (which explains why it is popular with users of other languages usually used for sys admin jobs).

If your job is glueing a few existing services together, you won't miss Generics much.


Um wow no.

Go is a language for people who write servers. It is really really good for those uses. Look at Docker, etcd, Kubernetes, Juju, Cloudflare, Soundcloud ...

And probably a ton that are internal to a company and not really exposed as a user-facing "Go Application™" (like the stuff behind google's downloads service, some of youtube's metadata processes, etc etc).

I think the fact that early on in Go's life someone called it a "systems language" really confused a lot of people. It's not a systems language. It's just a language. The channels, goroutines, and standard library happen to be really useful when writing networked servers.


Well it obviously depends on what kind of code you write. People writing certain types of libraries may benefit far more from generics than you would.


> Rob Pike has outlined the tradeoffs inherent with generics here: http://research.swtch.com/2009/12/generic-dilemma.html

First of all that post was written by Russ Cox.

Second, it already has been discussed multiple times that it only focus on C++, C#, Java approaches while cleverly forgetting generics implementations exist in multiple forms since CLU (1974) introduced them.

But Go advocates take that page as dogma and toss it around every time a generics discussion comes up.


It doesn't even cover C#, just C++ and Java. C# has it's flaws certainly, but it's a baffling omission.


In the comments, where the flaws about the document are pointed out.


The problem is that the code that needs generics is reusable abstractions in libraries. Thats probably 1-3% of code but it is also critically important and there is no convincing workaround.


That is Russ' blog post, not Rob's.


> [...] but because its authors and community is incapable of admitting problems when they see them.

What evidence did you see to make this conclusion? I can only find from their FAQ[0]:

"Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do.

Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a design that gives value proportionate to the complexity, although we continue to think about it. Meanwhile, Go's built-in maps and slices, plus the ability to use the empty interface to construct containers (with explicit unboxing) mean in many cases it is possible to write code that does what generics would enable, if less smoothly.

This remains an open issue."

[0] http://golang.org/doc/faq#generics


That answer has been there for a while. There hasn't really been any indication that the issue actually is open, other than a refusal to state outright "no generics in Go".

I can't decide if my biggest problem with that answer is that it suggests that the primary use case for generics is generic containers (when, really, the main benefit of generic containers is being able to implement generic algorithms on said containers, like pmap), or whether it's the suggestion that breaking type safety in a statically typed language is a feature.

interface{} is barely an improvement over void*. The need for it suggests an insufficiently powerful type system. Go should either have a type system powerful enough not to need an explicit convention to avoid it, or it should have been dynamically typed.


Quit whining.


I believe that this is evidence enough that they're downplaying the importance of generics.

Specifically, the claim that "maps and slices" can replace the ability to write abstractions such as futures, promises, observables as well as generic function such as map, reduce etc comes off as either naive or disingenuous

Furthermore, the "cost" of these features seems overstated to me. A lot of languages and runtimes already implement generics without significant compile-time or run-time overhead - why is it that hard for Go to do that?


I don't have the hard numbers to back up the cost question, but I believe one contributing factor to the claims appearing "naive/disingenuous" to you may stem from the fact that you may be looking at the language Go from a totally different perspective than the creators when they first envisioned the language (I could be very wrong in this regard):

"Go was designed to address the problems faced in software development at Google, which led to a language that is not a breakthrough research language but is nonetheless an excellent tool for engineering large software projects"[0]

They go on to list some concrete points on the type of problems they are trying to solve:

   - slow builds
   - uncontrolled dependencies
   - each programmer using a different subset of the language
   - poor program understanding (code hard to read, poorly documented, and so on)
   - duplication of effort
   - cost of updates
   - version skew
   - difficulty of writing automatic tools
   - cross-language builds
So while I can see generics helping their goal of, say "duplication of effort", I can also see it negatively impacting bullets "different subsets of the language" and maybe "poor programming understanding" since debugging generics can be extra-painful.

I might not agree with the way they value generics but to me, it does seem reasonable given their design vision and goals.

[0] https://talks.golang.org/2012/splash.article


With the right implementation debugging generics wont be hard. It doesn't have to be C++'s version of generics.

And I'm not buying the poor programmer understanding argument. Generics aren't that complex, they're just parameterized types. The fact that basic language libraries such as maps and slices cannot be implemented without them speak volumes about how fundamental they are when building abstractions.

My point is that most of the backpressure against generics seems to stem from perceived added complexity to the compiler and type system, and thats all. But I'm not convinced thats a valid argument. Truth be told, I'm not a language implementer. But I know that fast compilers and runtimes that implement generics exist, so I don't find the whole discussion believable.


> But I know that fast compilers and runtimes that implement generics exist, so I don't find the whole discussion believable.

Are you arguing that an implementation of generics in a programming language is free? (Whether it be performance or implementation complexity.) Because if not, then you admit there are trade offs. If there are trade offs, then it is conceivable that some circumstances (including programmer tastes) may lead to a valuation that is different from yours.

"Performance" of the compiler is a critical goal of the Go project. Could you point out for me an industrial strength compiler that supports a type system of your liking that can match the compilation speed of the Go compiler? (I can't think of one.) Because if not, then I'll have to invoke this: talk is cheap, show me the code.


> Are you arguing that an implementation of generics in a programming language is free? (Whether it be performance or implementation complexity.)

I am.

Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code.

Implementation complexity: You could add some constraints to generics, for example only interface types can be used as generic parameters, and all uses of variables/methods/functions with generic types need to have generic parameters given. In that case, there's no complexity for code that doesn't use generics. Also, generics could actually be implemented as a preprocessor that would simply insert appropriate casts from/to interface{} at calls to generic methods. Since all variables/functions in Go are declared and have known types, you could of course go further and eliminate most generic parameter annotations.


> Performance: if you replace all generics with interface{}, you get performance that is at better or equal to current Go code.

That is incorrect. Using `interface{}` incurs a significant performance penalty at runtime because you end up boxing everything. For example, you cannot cast a `[]interface{}` to an arbitrary `[]A`.

In other words, no, `interface{}` is not `void*`, sorry. If it was, Go would not be memory safe. (See golang.org for their definition of memory safety. It is strictly superior to a language like C, but e.g., less than a language like Rust.)


What I meant is, "better or equal to current Go code using the current version of polymorphism (which is `interface {}`)".

AFAIK it's not possible to write generic Go code without `interface {}` (or, alternatively, duplicating the code for each type).


Yes, but the tradeoff Go takes right now is "slow programmers," or "no generics." You are trading that in for "slow programs." This directly implies that generics have some sort of cost structure and are not free.

`interface{}` is very rarely used for writing "generic" code precisely because of its lack of type safety and performance implications. If you came up with a way to make it type safe without addressing performance, you've just implemented a generics scheme that will cause programs to be slower than they would be without generics (because people would start using them!).


I think it should be clear to every programmer that there are different trade-offs to be made when designing systems, including the trade-off between generic-code&fast-development&slow-speed and specific-code&slow-development&fast-speed. People that don't get that shouldn't be programmers, and people that get it should have the freedom to make their own trade-offs.

In other words, the only "cost" of generics, thus, is the social cost (there is no purely technical cost). Here, it boils down to the philosophical/political freedom-vs-safety question, and I strongly incline towards freedom. Go does not. Go's position is, if not wrong, at least loosing, since programmers demonstrably are using work-arounds (`interface {}`) when they need generics.


> Go's position is, if not wrong, at least loosing, since programmers demonstrably are using work-arounds (`interface {}`) when they need generics.

I just got through telling you that this type of use is actively discouraged, so no, people aren't using it as often as you might think.

If you want generics, you've got to pay for it. The implementation you've suggested requires a runtime performance penalty to use generics. Therefore, you have not demonstrated that generics are free.


D's dmd supports templates and is faster than gc.


Is there any evidence for this claim? After a quick Google session, the best I could find was a forum thread 4 years ago claiming that `dmd` was faster than `gc`. Is that still true today?


Not anymore. You're two years out of date


I think a lot of the complexity even in your examples of passing functions for generic actions like map/reduce is dealing with closures and scope. I don't know enough about golang to comment on its' internals, but as I recall there was a lot of work and effort that had to go into the .Net runtime and compilers in order to support lambdas and generics properly. Which, imho was more than well worth it.

There are likely other issues that golang needs to solve that are much higher priority issues, and there are flexible, even scripted languages that can handle higher level logic problems and scale very well. I wouldn't really expect to have to use generics for most of the problems I would look to go as a first language for a given problem.

Of course all of the above said, I'm a node.js fan and really like what it has to offer. It just depends on your use cases. Go is a really clean language/platform with a lot in the box, that I do appreciate. I would be surprised if they didn't support generics for v2, if not before. But I can see why they would want to punt the issue while there are bigger problems and needs to address.


You're claiming that they think generics have no value. That is incorrect. They just think there are other things that have more value.[1] In other words, they prefer a different set of trade offs than you do. I don't see how this could be reasonably considered "denial."

[1] - http://research.swtch.com/generic


Because they focus on Java and C++ on their arguments while forgetting other languages.


That link has been debunked over and over and over.

Why keep posting it? As you have seen in this thread, many people avoid Go not because it's not a very good language, but because of the way Go people deal with language problems and can't admit issues.

Being dishonest will just alienate even more people.


> That link has been debunked over and over and over.

The only point that post is making is that generics have a cost. Are you saying that is false?

> Being dishonest will just alienate even more people.

What are you hoping to achieve by insulting a large group of people? If your goal is to alienate them, then surely that is an effective tactic.


> The only point that post is making is that generics have a cost. Are you saying that is false?

Did you actually read the article?

> The generic dilemma is this: do you want slow programmers, slow compilers and bloated binaries, or slow execution times?

Wrong.

Additionally, not having Generics has a cost, too. People might disagree which cost is higher (Generics vs. no Generics), but acting as if there was a lower cost solution of "no Generics now, but retroactively add them later" hiding somewhere is just incredibly disingenuous and delusional.

Given your cost argument, there is absolutely no position under which "we don't have plan, but might consider it in the future" would give a favorable outcome. Why not just be honest and tell your users that Generics will never arrive?

> What are you hoping to achieve by insulting a large group of people? If your goal is to alienate them, then surely that is an effective tactic.

Oooooh. Burntsushi pulling his "whine whine you weren't nice to me first!", how unexpected ... not. It's a fascinating pattern which happens as soon as you run out of on-topic arguments.


> Additionally, not having Generics has a cost, too.

The article says it: "do you want slow programmers, slow compilers and bloated binaries, or slow execution times." The first "slow programmers" cost is addressing the absence of generics in the language. Thus, it admits a cost.

> but acting as if there was a lower cost solution of "no Generics now, but retroactively add them later" hiding somewhere is just incredibly disingenuous and delusional.

... Nobody is acting that way. I've said nothing about the relative weight of any cost, nor have I claimed that a lack of generics has no cost. I mean, the link I gave you admits that a lack of generics has a cost right there. You even quoted the relevant portion.

> Given your cost argument, there is absolutely no position under which "we don't have plan, but might consider it in the future" would give a favorable outcome. Why not just be honest and tell your users that Generics will never arrive?

I don't understand what point you're trying to make. Are you saying that the Go language maintainers are purposefully lying to everyone? Do you have evidence of this claim?

> It's a fascinating pattern which happens as soon as you run out of on-topic arguments.

And insulting people doesn't fit that pattern? Yikes.


> Given your cost argument, there is absolutely no position under which "we don't have plan, but might consider it in the future" would give a favorable outcome.

Sure there are, including the following possibilities: 1) There are situations in which generics are a net benefit and situations in which generics are a net cost, and currently Go's target are is the latter, but because of drift in what people what in given domains, it evolves toward the former, 2) New advances in understanding of language design and implementation change the tradeoffs of generics such that they are a net benefit in places where currently they are a net cost, 3) The reason generics are a net cost in the current situation of Go isn't fundamental as a featre, but a matter of opportunity cost given other things that were and are being implemented in Go that implementing generics would tradeoff. A future implementation that doesn't disrupt non-generic-using code once other higher-priority features are implemented wouldn't be a net cost. But that's farther out than Go's current roadmap.

> Why not just be honest and tell your users that Generics will never arrive?

Because its not honest to state a decision that hasn't actually been made.


> New advances in understanding of language design and implementation [...]

"New advances" as in "the last 50 years of progress in language design which we have conveniently ignored"?

There are languages from the 60ies which are better than Go (but lacked Go's distinguishing feature, the Google brand).

> Because its not honest to state a decision that hasn't actually been made.

Given the constraints they have already made a decision.


> "New advances" as in "the last 50 years of progress in language design which we have conveniently ignored"?

No, new advances as in, "new advances". The universe changes, and the context in which the decision not to prioritize generics now was made is not fixed.

> There are languages from the 60ies which are better than Go

"Better" is both subjective and use dependent, and, in any case, that claim is irrelevant to the point under discussion, which is whether or not it is logically possible for the cost tradeoffs to disfavor generics in Go now but favor them in the future.

> Given the constraints they have already made a decision.

Given the current constraints they have already made a decision not to develop generics now.

They have not made the decision you claim that they would be "honest" to announce, to wit, that Go will never have generics.

It may be that it won't, but that's a not a decision that they have made (nor is it a decision that it would likely ever make sense to make. Why ever say "never"?)


From what I've seen is that th Go team has no desire to change the core language syntax at this time. They are spending most of their time on toolchain and runtime improvements.

Go does have generics for map but you can't create your own. I think they will add user generics at some point, but it may be a long while before that happens.


My understanding is that the Go team says they can't figure out how to make generics work nicely, that's why they haven't added them.

Also, type casts don't cause runtime panics. You can use type-based switch/case or check the "ok" return value from the cast to see if it worked.


That's basically what Java said in 1995.

There is a reason why Java completely abandoned that position.


Did Java make generics work nicely, or did they just bolt them on?


> A similar problem with CoffeeScript (conflation of declaration and assignment + scope rules)

That's an issue you simply cannot fix in CS, you need a new language/fork (not having var/let is at the heart of the language's syntax). I wouldn't compare it with Go's lack of generics.


> I wouldn't compare it with Go's lack of generics.

Why? It feels like forking Go would be the fastest way to get Generics.

But on the other hand, the people who are able to pull that off usually just stay away from Go in the first place.


This is in an interesting contrast with Apple's Swift. It seems that Chris Lattner and the Swift team are very willing to listen the input from users in this early phase of the language. The whole way the Swift is being developed is unlike anything else Apple does. Swift core team responds to you in Twitter. The product is released in such an early state that it is frustratingly buggy and slow to use. But it has a regular release schedule and it gets improved in both stability and speed every other week. I don't know if this was agreed on the top level, or did Chris just has enough decision power to just go with this more modern style of release cycle.


I also find Go pragmatic but lacking abstraction power. The other day I needed a stack, and the best solution I could find was this: https://groups.google.com/d/msg/golang-nuts/iwlzqNa4h3g/xCy3...

    to be honest, if i need a stack, i usually implement it for the type 
    in question, or inline, as it's only a very small number of lines: 

    type stack []T 
    func (s *stack) push(t T) { 
        *s = append(*s, t) 
    } 
    func (s *stack) pop() T { 
        n := len(*s) 
        t := (*s)[n-1] 
        *s = (*s)[:n-1] 
        return t 
    }
And that's what I'm using...


It's 10 lines of very obvious code. Isn't that a good thing? Do you really need stack.New<T>()?


Yes, I do think so. Then I could keep thinking about the "business problem" instead of googling for half an hour because I can't believe there is no one reuses a stack in Go.

Also, it could be something much more complicated than a stack, like the data structures in the STL... but that point has already been made elsewhere.


    > Go doesn't let you build abstractions - it offers what 
    > it does, and if its not enough - tough luck.
This seems contradictory. Go offers primitives, and lets you build exactly the abstractions that make sense in your domain on top of those primitives. The argument here appears to be that the primitives are too low-level, which is a fair-enough point, but not at all what you're claiming.


No, your parent is right.

Of course: turing tarpit, greenspunning, yadda yadda yadda, but his point remains: Certain abstractions with a low cost/benefit factor are just not expressible in "idiomatic" Go.


"...incapable of admitting problems..."

From the Go FAQ:

Why does Go not have generic types?

Generics may well be added at some point. We don't feel an urgency for them, although we understand some programmers do.

https://golang.org/doc/faq#generics


If you read the link you posted, you would know why people say that Go devs are incapable of admitting issues.


Seriously?

"...we understand some programmers do... ...we continue to think about it... ...This remains an open issue."


You sound confused. Denying the existence of a problem and not wanting a particular proposed solution are not the same thing.




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

Search: