HN user

ootachi

1,513 karma
Posts8
Comments461
View on HN

I apologize for the above comment. I am being extremely uncharitable to Go and I retract what I have said.

In particular I apologize for bringing this up in every Go discussion.

Java avoids casts in most cases with generics, it supports inheritance, and it has a simple type system. Ditto with C#. (I also haven't heard people complain about the complexity of F#'s type system, so I'd point to it, but I don't know F# enough to be able to say whether it's a good point or bad point in the space here.) OCaml also supports inheritance, although its object system is kinda weird (in that it doesn't really fit with the rest of the language; I wouldn't say it's overly complex though).

Basically I don't think that Scala's complexity should burn us on type safety in general. I think Go and Dart, for example, are an overreaction to the complexities of type systems like those of Scala (no generics and null pointers in the former, and unsound covariant generics and null pointers in the latter). There is room for a statically typed language that brings the benefits of type safety that make programming easier without the complexities that make programming harder; the fact that we haven't found that sweet spot yet doesn't mean that we should just throw up our hands. I'm not convinced that the sweet spot is either unsound or requires casts.

How do you have greater control over whether your code generates garbage in Go? The only difference between Java's memory model and Go's memory model is that, in Go, you can put structs inside other structs (and unsafe code I guess, and note that you can get some of the "structs inside other structs" benefit from inheritance in Java). That's it. The stack/heap distinction is no different between Go and Java.

The idea that "the suboptimality of Go's GC is much less significant" is just wrong -- Go has the exact same memory model as Java, only it's less well equipped to deal with it than Java is because its GC is so suboptimal. I'm just countering the oft-quoted statement that Go's memory model is somehow closer to the metal than that of Java -- it isn't.

To optimize allocations in Java, you use free lists and make fewer variables escape so they can be stack allocated. To optimize allocations in Go, you use free lists and make fewer variables escape so they can be stack allocated. Java has a wealth of allocation profiling tools available at its disposal. Go has some too. Go doesn't provide anything over Java here.

I think your warnings about complexity in the type system are prudent, but your comment about casting is off. Casting (with the exception of primitive types) is a very blunt hammer to bash your way out of a type system. The MLs have a simple type system, yet you almost never need to cast. It's worthwhile from a language design perspective to try to eliminate the need to cast entirely, and I believe you don't have to complicate your type system to do so.

Also, you note that "many people prefer static typing", but then you suggest Clojure...

Why not just use Java?

Java was designed as a reaction to the complexity of C++. Scala was, in turn, designed as a reaction to the simplistic nature of Java. It sounds like you prefer minimalism, and in that sense Java is a better choice for you. That's what it was designed for: simplicity.

Go has C++-style classes. Anonymous fields are just C++ multiple inheritance with a different name (and without virtual functions or downcasts).

Now you've moved the goal posts. You can write free lists manually in Java as well. Doing so is incredibly awkward in Java or Go, compared to C++ where placement new makes it fairly straightforward (and moreover, you can use reference counting without too much trouble either). You can also use a real-time GC for Java, and you don't have that option in Go. This is perhaps uncharitable, but you're basically saying "our GC is bad, but you can work around it so it's okay".

Furthermore, you're implying that I'm saying something false ("as if they were facts"), but acknowledge that it is "possible". So I'm actually not seeing where I was wrong.

And I have used Go. I didn't like it. I realize I'm in the minority, but there are valid reasons for disliking Go.

Why would you move from Haskell to Go? There's a night-and-day difference between them. I don't understand why you'd switch to a language because of the features it's lacking, unless you think those features are a bad thing (and I have yet to see a reason why generics and TCO are a bad thing).

Nonsense. You would hate Android written in Go, because of the GC pauses. Dalvik has a concurrent garbage collector; Go has a stop-the-world one.

Up until the point you want to return an object from your container, sure. Then you have to return a Comparable and the user has to downcast it into the right object.

Plus, you pay the overhead of boxing.

Chrome could not be written in Go, due to the stop-the-world GC. 200ms GC pauses are completely unacceptable for a web browser.

I bet most people get the "protected" one wrong, because it's actually strictly less restrictive than package access in Java. That is, protected members can be accessed by anyone within your same package. Do you reject people for not knowing that any class in the same package can access protected members?

If so, you probably just weeded out a huge percentage of Java programmers.

People don't use Web browsers for video chat. They use Skype. Getting people to change will be hard, especially since the browser offers no real benefits over Skype.

I'm not saying we shouldn't try to get people to change, only that it will be hard and Skype interoperability is a very legitimate thing to want to achieve.

Odd that you say that, because the language that's most similar to Go here is Java, with its checked exceptions. The same reasoning that led to Go's error codes (that you should always handle your errors) led to checked exceptions. The fact that people generally think checked exceptions are a bad idea is a point against Go, not in favor of it.

Checked exceptions are superior to Go's error return codes anyway, since they make it easier to bubble your errors up to your caller.

This doesn't seem to have anything to do with type erasure, does it? It's needed for type-safe generics. Even without type erasure, you still need type safety. If your generics are always covariant (like Dart's are), you break type safety.

I think the mistake the Java designers made here was going with use-site variance instead of definition-site variance.

I have a feeling you're going to get a bunch of type theorists instead of programmers who get things done if you ask about Java's syntax for use-site contravariance.

What do you do then?

If the answer is "panic", note that exceptions are superior here, since exceptions let you "panic" without having to litter your code with those calls.

If the answer is some form of "log an error message", exceptions are superior, since you can group multiple related calls into one try-catch block and avoid having to check at the site of each and every call.

If the answer is some form of "return a different error code to your caller", exceptions are superior, because you can catch many different types of exceptions in one try-catch block and re-throw a different exception.

Because panic/recover are bad exceptions (recover can't specify the types of the exceptions it wants to recover from), and the libraries don't use them. Having to check errors is annoying since most of the time you want to bubble the error up to your caller. This is exactly what exceptions (or the error monad) do for you. In Go you have to do it manually.

Anyway, Go does have exceptions. It just doesn't make much use of them. Seems a shame to not use a useful feature, but oh well.

defer is not reliable if you forget to call it. RAII is much more foolproof than defer in this way. You can forget to call defer, but you can't easily forget to call the destructor.

Go has exceptions. They are called panic/recover.

This has been explained to you time and time again. You keep posting this exact same comment, complete with the "COME FROM" analogy. Then it gets explained to you that panic/recover are an exception system. Then you ignore it. It's really tiresome.

Additionally, people get around the lack of generics in C with macros. Go doesn't have those.

For that to be true, the Go developers would have to be open to adding research ideas to the language. Java is (for example, generics). Right now Go's developers are not open to this. As a result, Go is not publishable.

Guilty as charged. I do want a functional language like Scala, because I believe that school represents a better design. That school of language design saves me the headache of null pointers; it helps me write unit tests with QuickCheck; it allows me to define custom generic collections; it places emphasis on having a fast GC; it features monadic style to help with error handling.

There's active marketing and there's passive marketing (brand association). Go is popular because of its association with the brand of Google and the brand of Pike and Thompson. A lot of people like the language on its merits (although I disagree with pretty much every decision they made), but I believe the reason the language got traction is because of its brand association.