Most active commenters
  • NateDad(5)
  • AlexandrB(3)
  • meowface(3)

←back to thread

131 points apta | 38 comments | | HN request time: 2.146s | source | bottom
1. carbocation ◴[] No.9266352[source]

My summary of the author's points: no generics, inexpressive, no good package manager, procedural.

Of these, caring about the fact that it is procedural seems pure opinion. Lacking a package manager is not really a language issue (PHP's package manager, for example, is not coupled to the core language).

So, we are left with the lack of generics and the lack of expressivity. I'm not deep enough in the weeds to be able to argue pro/con for generics intelligently right now, so I will concede that as a concern that has been raised by many.

The lack of expressivity seems to be an inexorable consequence of the goal of simplicity, so I'm sympathetic. That said, it seems to be a tradeoff acknowledged by Go's authors, not an oversight.

Overall, these points don't convince me of the author's thesis (or, at least, they don't seem to justify the title's degree of inflammation).

replies(5): >>9266432 #>>9266452 #>>9266511 #>>9269687 #>>9281940 #
2. AlexandrB ◴[] No.9266432[source]

I thought the "sum" example was pretty damning. Bug count scales with code length so writing tons of boilerplate code to work around language limitations means you're introducing bugs.

replies(4): >>9266445 #>>9266448 #>>9266915 #>>9267114 #
3. carbocation ◴[] No.9266445[source]

I believe that the purpose of `go generate` is to lessen the risk of this type of thing by handling the repetitive code generation for you, but I do agree that it's a limitation. If done by `go generate`, it's an additional procedure that you have to learn; if done by hand, it's a bug risk.

replies(1): >>9266724 #
4. jmtulloss ◴[] No.9266448[source]

In my opinion, bug count scales within a code base with code length, but you can't really compare languages and say that the shorter one must contain fewer bugs. A more expressive language means you can cram more bugs in fewer lines.

replies(1): >>9266459 #
5. pivo ◴[] No.9266452[source]

I hadn't really looked at Go before, but I have to say the generics issue reminds me of Java 10 years ago before it got generics. Java also had the goal of being simple, which is probably why it's so popular, but for me it was always too simple in the sense used in TFA (haven't tried Java8 yet though.) At least it looks like Go has higher order functions, but I don't see how they will be that useful without generics unless you subvert the type system.

I definitely think the too-simple nature of Java is the reason behind all the reams of boilerplate Java code found in most any Java project, and I can't see how Go would be any different. It seems like a shame not to have learned that lesson.

replies(2): >>9266919 #>>9267041 #
6. AlexandrB ◴[] No.9266459{3}[source]

Take a look at this: http://programmers.stackexchange.com/questions/185660/is-the...

Bug counts/kloc seem to be consistent across languages.

replies(1): >>9266504 #
7. AlexandrB ◴[] No.9266504{4}[source]

To add to this, implementing a bunch of boilerplate often means copy/pasting code. That means you risk introducing mistakes where one copy is wrong[1].

[1] http://www.viva64.com/en/b/0260/

replies(1): >>9267387 #
8. mmcclure ◴[] No.9266511[source]

> PHP's package manager, for example, is not coupled to the core language

"Lacking a package manager isn't a language issue, this language that's nearly universally derided doesn't have one."

I see what you're saying, but that strikes me as a really bad example. That being said, it is strange to me that a modern language wouldn't have any reasonable story around package management. The argument I've most commonly heard is that applications should be very small bits of functionality, thus making a full-blown package manager unnecessary...sure, that seems reasonable...except dependency management is still (aside from the whole generics flame war) one of the most common complaints I've heard from Go devs.

To be honest, I don't understand all the vitriol. That's by far the most bizarre thing about Go to me.

replies(2): >>9266687 #>>9266758 #
9. shebson ◴[] No.9266687[source]

A more appropriate example might be Python. It didn't ship with Pip by default until Python 3.4 (released in 2014).

10. meowface ◴[] No.9266724{3}[source]

Code generation is a giant spiked mallet for a nail which can easily be screwed with a small screwdriver. It has its uses, especially for generating schemas (like what Protobuf and Capnproto do), but for generating actual function implementations it's kind of absurd. `go generate` is a nice tool but it's not even remotely a solution to the no-generics problem.

Of course, the problem is that for the compiler implementation, those traits are completely reversed (adding generics at this point is like hitting the compiler with a mallet); and that happens to be Go's primary excuse for lack of generics/templating/macros/anything sane. I think dev ease-of-use matters a lot more than core dev ease-of-use though. Even if the compiler must grow in complexity and average compile time, the benefits to devs are worth it.

replies(2): >>9266962 #>>9269292 #
11. benihana ◴[] No.9266758[source]

It's bizarre to me that you started your post by dismissing an entire language based on popular opinion then end it by saying you don't understand the vitriol people have about a different language.

replies(1): >>9267133 #
12. slantedview ◴[] No.9266915[source]

This, and boilerplate != simplicity. The D example in the article - now that is simplicity. Language designers would be well served to acknowledge this.

13. davecheney ◴[] No.9266919[source]

If you want a more complex Java you can have Scala. Scala remains hostile to newcomers with an almost vertical learning curve. I don't think anyone can seriously argue that commercial programmers need a more complex language.

replies(2): >>9267046 #>>9268612 #
14. NateDad ◴[] No.9266962{4}[source]

No one has ever said that the compiler implementation would be too hard, and that's why there's no generics in go. People need to stop saying that, because it's bullshit.

replies(1): >>9267164 #
15. Someone ◴[] No.9267041[source]

I think the too-simpleness of Java 1 also has made Java 8 more complex than it could be. Java got generics 'the easy way' through reification, and that gave us the mess that is mentioned in http://java.dzone.com/articles/whats-wrong-java-8-part-ii:

"the methods of these interfaces have different names. Object functions have a method named apply, where methods returning numeric primitives have method name applyAsInt, applyAsLong, or applyAsDouble. Functions returning boolean have a method called test, and suppliers have methods called get, or getAsInt, getAsLong, getAsDouble, or getAsBoolean."

The solution that go offers for such problems seems to be to deny that there is such a thing as libraries and to promise to deliver migration scripts whenever changes in the language or its libraries break existing programs.

That approach works fine now, but I am not sure it scales to a situation where go is truly successful; in particular, I think go, at some time, will have to allow for dynamic linking to support commercial libraries, if it wants to become truly successful.

On the other hand, the times of copy protection on software being normal are far behind us, and CLR has an ecosystem for commercial libraries, that decompile so well that CLR libraries do not differ much source code. Maybe, I am underestimating the willingness of commercial vendors to start shipping libraries in source form.

replies(1): >>9267211 #
16. frowaway001 ◴[] No.9267046{3}[source]

"Why should I ever wash my hands before a medical procedure? It just makes things more complex!" –– Surgeon, ~1700.

replies(2): >>9267667 #>>9267725 #
17. falcolas ◴[] No.9267114[source]

As a programmer who is writing Go for a living: the lack of generics is not actually that big of a problem in your day to day work.

Yes, if you want to generalize code to release a library to a much wider audience, you'll either end up writing quite a bit of duplicate code, using the code generation tools, or diving into the "reflect" package (which would let you write Sum in one method).

That said, I've never had to do either of these in writing about 10k lines of Go code.

18. mmcclure ◴[] No.9267133{3}[source]

I personally don't understand the vitriolic posts on Go. I personally do understand the vitriolic comments about PHP, of which there are examples that are well-reasoned and go beyond "no generics!"[1]

[1] http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design

replies(1): >>9267739 #
19. meowface ◴[] No.9267164{5}[source]

From the Go FAQ (https://golang.org/doc/faq):

>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.

Not hard as in "can't do it", but hard as in too hard to implement without adding the ever feared "complexity".

For the record, I like Go and its philosophy, but I think, above all other issues with the language, the lack of generics is a huge weakness and will eventually be looked back on as a mistake. Not just for not having them before 1.0, but also for waiting as long as they did for adding them, assuming they ever do add them.

replies(1): >>9267371 #
20. waps ◴[] No.9267211{3}[source]

I don't get where people get the idea that Go is simple.

1) go has generic functions : http://golang.org/pkg/builtin/, they're just not accessible to you

2) go has generic types : slices, maps, and channels, all of which have slightly differing behaviour, including some highly counter intuitive and contradictory behaviour (example: slices are pass-by-reference, arrays are pass-by-value. In other words []int and [5]int behave entirely differently)

3) go has overloaded functions : http://golang.org/pkg/builtin/, they're just not accessible to you

4) go has exceptions (panic/recover), negating all the advantages of Go error checking, and providing zero fixes for the problems it introduces (finding the source line where an error happened and if/how multiple errors are related. Easy in Java/C++/..., hard in Go) (in C++ you have to be aware of whether any external code you use throws exceptions ... in Go you have to be aware if any external code you use panics. And if you say I haven't dealt with it, that means that you quite literally haven't dealt with it. Same as in C++. External libraries throwing exceptions is perfectly fine ... as long as they never actually throw an exception. Panicing standard library is fine ... as long as it doesn't panic ... If you're looking for correct code, it is of course not fine)

5) Go's "simple" threading and panics. Try crashing a Go program with shared data with a null-pointer derefence in the shared data. Someone please explain to me how the resulting output is simple.

6) golang's own compiler and standard library are not in fact idiomatic Go. This goes from small problems (like total lack of unit tests in quite a few places), to larger ones, like not using interfaces for logging.

7) interface{}. I just grepped a reasonable, thoroughly reviewed codebase I've written, of several tens of thousands lines of Go. Result: 2.7 uses of interface{} per 1000 lines of code.

Is this what people here call simple to think about code ? I would argue that you don't understand a codebase until you've read it. That's a certainty. So can we at least agree there's a point where verbosity no longer increases readability ? I hope you can see Go is far past that point.

Go's type system : riddled with exceptional behaviour. Literally it says "type system applies unless it's doing <-, cap, len, copy, new, append or delete calls", in which case we do something custom. The resulting behaviour, of course, is inconsistent with Go's type system (which is really the point of the code of course, unfortunately, there's surprises buried in there, and those calls are inconsistent with eachother as well).

All of these are implemented as exceptions in the compiler. I would warn you about this link : once it is seen, it cannot be unseen :

https://github.com/golang/go/blob/master/src/cmd/internal/gc...

The irritating part is that this sums up Go mailinglist behaviour quite well. Coding practices is for you, not for us, the Go authors. Generics ? Of course we need that, but you obviously don't as you're a bad programmer. And if you're asking for something else that must mean you suck. Overloading ? Ditto. Generic types ? Yes for us, not for you though !

Of course, all of these claims are thrown around and when you actually read the compiler code you wonder ... do these guys know about type systems ? Don't these guys know about the standard coloring algorithm ? Why aren't they using extremely-well-known algorithm X for this ?

In other words, it really looks like the compiler was (and is) written by someone who last opened a compiler book in the 70s. But reading the mailinglist, you'd think they were the central authority on compiler theory and you're stupid. This is in fact not the case.

Go works and feels like a late-90s language like Oberon. Clean at the surface, with lots of buried ugliness. Lots of weird custom datatypes, forms and parts of the standard library that are not implemented in the language itself. It's why I switched to C/C++. Go is simply the same as those old languages we moved away from. There is nothing in Go that cannot be achieved better and more flexible in C++, D and Rust.

replies(1): >>9267436 #
21. NateDad ◴[] No.9267371{6}[source]

The type system is a concern about the complexity for the users of Go, not for the compiler developers.

replies(1): >>9267702 #
22. NateDad ◴[] No.9267387{5}[source]

You assume that Go's simplicity means you end up copying and pasting a lot of code. This is just not the case. In juju (https://github.com/juju/juju), a ~300kloc project, we have approximately one single type that we've copy & pasted where a generic implementation would have been better (it's a set). And honestly, implementing full set functionality was not even really necessary, someone just felt like doing it.

23. zzzcpan ◴[] No.9267436{4}[source]

> Clean at the surface, with lots of buried ugliness.

Maybe we will see a DSL that compiles into Go to fix this. Like we have for Javascript.

replies(1): >>9267615 #
24. mmastrac ◴[] No.9267615{5}[source]

What would be the point? You may as well just target LLVM.

replies(1): >>9267676 #
25. davecheney ◴[] No.9267667{4}[source]

What a feckless comparison. Don't mistake something taking more time with something being more complex.

26. zzzcpan ◴[] No.9267676{6}[source]

To benefit from the whole Golang ecosystem.

replies(1): >>9270085 #
27. meowface ◴[] No.9267702{7}[source]

How exactly? Ignoring issues of backwards compatibility for the moment, I don't think Java's introduction of generics added a ton of complexity for developers, and I don't see why Go would either. In Java's case it seemed like the complexity was definitely on the compiler side, due to their type erasure approach.

I admit I'm not an expert in programming language design though, so I may be completely wrong about both Java and Go.

28. Gigablah ◴[] No.9267725{4}[source]

Comparing Scala's complexity to a life-saving procedure says more about your own self-importance than anything.

replies(1): >>9278157 #
29. Gigablah ◴[] No.9267739{4}[source]

It's 2015, the PHP ecosystem has progressed. Citing that blog post hurts your argument more than it helps.

replies(1): >>9268521 #
30. NateDad ◴[] No.9268521{5}[source]

The blog post is only three years old, and the problems it brings up are basic language problems. Has the language really changed that much in three years? And if so, wouldn't that leave all the existing projects out in the cold?

Serious question. I don't know the PHP community at all.

replies(1): >>9272991 #
31. modersky ◴[] No.9268612{3}[source]

We have data to contradict this argument: Over 400'000 people have enrolled in an online Scala course with a success rate twice the industry average. "Almost vertical learning curve?" Please!

32. MetaCosm ◴[] No.9269292{4}[source]

As someone who has repeatedly done code generation on the C++ side to avoid build-hell (text files with expansion into C++ files) -- I can't agree with this. Your trivialization of complex C++ build times is nonsensical and reeks of inexperience -- it ruins everyday -- it ruins cycle time -- it sucks joy and creativity out of development... long build times are atrocious which is why insane effort is being spent to try to lower them in C++.

Lots of C++ "features" on banned on major projects because of complexity and build time issues -- templates, exceptions, operator overloading...

33. sethetter ◴[] No.9269687[source]

"Expressiveness" seems like a subjective measurement to me. Also, from what I've gathered, Go attempts to be more convention oriented and is centered around doing things the "one true way". The Go formatter is an example of this. Perhaps this is just a result of that philosophy.

34. mmastrac ◴[] No.9270085{7}[source]

Fair enough.

35. kmshardware ◴[] No.9272991{6}[source]

I do a fair amount of PHP (really, I run hhvm, but let's say modern php), and effectively nothing in that article affects me.

No one should be using mysql_* anything; no one should have been using it for years. It's deprecated. It throws warnings when run. PHP's love of forced backward compatibility causes some very interesting things to be remained.

Paamayim Nekudotayim isn't called that anymore and hasn't for a long time.

The author raises issues about things like @fopen(url) - no one I know, or myself, has ever done that. It makes absolutely no sense to.

PHP has autoloading/"modules"/dependency injection/a proper package manager/etc (article is from early 2012: composer was largely popularised from what I can see a bit after that).

The author complains about no stack traces - sure, there won't be any on a single file bad function name, but any time I've used a proper request library or anything best practice, I've gotten a proper stack trace with file names, lines, etc.

--

There are a lot of somewhat odd complaints or wildly strange, like "No Unicode support" and "PHP is naturally tied to Apache. Running it separately, or with any other webserver, requires just as much mucking around" which makes absolutely no sense to me. The author of this article even says that if you want to run two versions of PHP, you rebuild Apache? That's absurd.

> 'The “bunch of files” approach, besides making routing a huge pain in the ass, also means you have to carefully whitelist or blacklist what stuff is actually available, because your URL hierarchy is also your entire code tree'

None of this makes sense either: unless you are doing some seriously outdated horrors, you have effectively one /index.php router and a public asset folder for the webroot.

replies(1): >>9275422 #
36. NateDad ◴[] No.9275422{7}[source]

Thanks for typing all that out. It's great to hear that most of what that article complains about is not affecting current PHP projects. I know there's a ton of PHP out there, so it can't be that bad. :)

37. krenoten ◴[] No.9278157{5}[source]

Strong type systems absolutely save lives.

38. ralfn ◴[] No.9281940[source]

>So, we are left with the lack of generics and the lack of expressivity. I'm not deep enough in the weeds to be able to argue pro/con for generics intelligently right now, so I will concede that as a concern that has been raised by many.

"Generics" is not a feature, its a bugfix. It refers to the type checker not rejecting perfectly fine code. In practice, you can just read 'generics' as 'this product does not contain asbestos', or "the mandatory type checker does not reject perfectly fine code".

Type systems are supposed to help you catch bugs at an earlier stage than run-time execution. However, implementing a type system is very hard and academic in nature, and the type of people who are good at making production ready high performance compilers generally aren't very good at type checkers. This is why many languages initially launch with a broken type system (and often a broken garbage collector), but eventually patch things up.

The problem Go has, is that its main author makes such cringe-worthy statements about generics, that we now have a large group of enthusiastic people who, on the basis of authority of the author, exclaim equally confusing remarks. Everything got so defensive that this typical launch bug, normally fixed with a release or two, is now part of the culture and DNA of this particular ecosystem. The sad thing is, these are all talented people, that instead of impressing us with their awesome skills, are embarrassing themselves in front of anybody who ever read anything about category theory.

For example, here's a "generic" algorithm to fold the (+) operator in Javascript:

        function( xs ){ var result = 0; for( var i=0; i<xs.length; i++ ) result = result + xs[i]; return result }

No type checker, no fuzz. There is nothing complicated here. But if you translate this to Go, you would you would need to copy this code over and over again for every potential leaf type you want to use this algorithm with and change only the type signature. The complexity is actually the result of a mandatory type checker that is broken by design. The most simple solution to support 'generics' would be to make the type signature optional.