Live data from Hacker News

Why Go Is Not Good

yager.io

351–360 of 367 posts

Re: Why Go Is Not Good

#351

Earlier quoted context omitted.

> You get out of having to write your own GC No, you really don't. The built-in GC is nothing like the GC needed for lots of other languages.

The built-in GC is nothing like the GC needed for lots of other languages. Don't write those languages in Go.

That kind of defeats the whole idea that it's a good language for writing other languages in.

Not to mention that to use the GC, you'd have to carry the whole baggage of Go's runtime with you in the new language. And that's Go's GC is not that good in the first place.

Re: Why Go Is Not Good

#352

Earlier quoted context omitted.

> Parametric polymorphism does not simplify code, it obfuscates it as now you have to see _what_ is calling it. This is backward. A function, polymorphic or otherwise, does not influence code that does not call it. Modulo far-reaching side effects of course. It's when you look at the call site that you have to figure out what this strange `fold` function could possibly be about. I'll grant that polymorphic functions…

> A function, polymorphic or otherwise, does not influence code that does not call it. Obfuscate does not mean influence, it obfuscates it you now have to follow the rabbit hole to where the type information is (language detail but it is how almost all parametric polymorphism is) which makes reasoning about it a pain. > That's an implementation detail, and mostly false anyway. No it's not 'unbound' parametric polymor…

You need practice with an ML derivative. Fetch a Haskell tutorial, then go write a little project of your choice that requires a few dozens lines.

> Obfuscate does not mean influence, it obfuscates it you now have to—

Wow, slow down. And give me an example, or I won't know what you mean.

> No it's not 'unbound' parametric polymorphism in a compiled language has to produce symbols for any visible (not internal) function as there would be no way to know what might get called.

Your lack of punctuation is hard to parse.

Anyway, it doesn't work like that. C++ for instance doesn't instantiate the polymorphic function for every possible type. Actually, it tries to compile monomorphic code first and only specialized polymorphic stuff as needed. This is why you need to actually use template code before the compiler can check it properly. (Notice how some error messages only surface when you use template code?

Let me give you an example (untested code):

  template
  T sum(vector vec)
  {
    T sum = vec[0];
    for (int i = 0; i 
Why the generic code? Because I'm likely to perform sums on integers, floating point numbers, complex numbers and other fancy stuff. I fail to see how this approach obfuscates anything, since it let me write less code.

Now my C++ compiler will not compile this function for integers, floats, and every user-defined class I have in my program. If my program only uses it on vectors of integers, it will only instantiate the integer version, even if I have floats in my program.

> Yes any compiled language does how on earth would you call a symbol that took a bool vs a size_t (I recommend you look at how ELF works).

Muhaha, you foolish mortal. Let me tell you how this works in OCaml.

Under the hood, OCaml data are one of two things: an integer, or a pointer to heap data. The compiler can distinguish them thanks to the least significant bit: 1 when it is an integer, 0 when it is a pointer.

This is possible because in most machines pointers are generally aligned to word boundaries, and words are almost always 16 bits or more. Integers on the other hand have one less bit. On a 32 bit machine for instance, OCaml integers fit in the 31 most significant bits. More precisely, when the program sees a 32 bit word whose value is 43, it knows that it's an integer, and that the underlying integer is 21 (meaning, 43>>1).

You will note this suspiciously looks like a dynamic language implementation of runtime tags. It is a bit cleverer than that. First, the code is statically checked, so it never performs any runtime check with respect to this tag. The garbage collector on the other hand knows little about the program, and needs a way to distinguish raw data from heap pointers to do its job.

Now polymorphic code. In OCaml, a polymorphic function knows nothing about its polymorphic arguments. This is important, because it mean the code inside won't ever inspect nor modify the values at runtime. Take this example:

  let app f x = f x         (* app: (a -> b) -> a -> b *)
`app` is function application reified into a function. Yes it's silly in most cases. Bear with me. Look at its type. It accepts two arguments (of type a->b and a respectively), and returns a value (of type b). As you may have noticed, we have no frigging clue what those `a` and `b` mean. That's what it means to be polymorphic.

Now let's call the function on actual arguments.

  app (fun x -> x + 1) 42   (* the result is 43 *)
Okay, so the first argument is a function from integers to integers, and the second argument is… 42 (an integer). And poof magic, it works.

Under the hood it's not complicated. `app` knows that its first argument is a function, and it knows that the type of its second argument is compatible with that function. Since the first argument is a function, at runtime, it must be represented by a pointer to the heap. More specifically, it will point to a closure on the heap. We don't know much about this closure:

  +---+-------+
  | f | Data… |
  +---+-------+
We don't know anything about that `Data` stuff, but we do know that `f` is a pointer to code that will accept at least one argument.

Then there is 42. In the CPU it will be represented as 85 (42So… `app` has 3 things: a pointer to a closure, a pointer to a piece of code, and an opaque blob of data (which happens to be an integer, but it doesn't know that). What it must do is clear:

  - Push the opaque blob of data to the heap.
  - Push the pointer to the closure to the heap.
  - Call f
And voilà, we have polymorphic code at the assembly language level. By carefully not inspecting the data, it works on every kind of data. No need for de-duplication.

Still, we don't have our result. We just called `f`, which has 2 arguments to contend with: its closure, and its "real" argument: 42. Now as you can see in the source code, `f` is not polymorphic at all. It works on integers. So it knows about its argument. Actually, it knows two things: the `Data` part of the closure is empty, and its argument is an integer. So it just adds 1 to 42 (possibly using some clever CPU arithmetic involving the LEA instruction), pops 2 elements off the stack, and pushes its result (43, which we represent as 87).

Now we're back to our polymorphic `f` which has this 87 blob of opaque data at the top of the stack. Well, it just returns it to its own caller, who hopefully will know how to handle that data.

---

As I have just illustrated, there is no need for duplication in the first place. Polymorphic code in OCaml generates polymorphic code at the assembly language level. And this was a naive compilation scheme. "Dumb" turns out to be sufficiently smart. De-duplication out of the box if you will.

And about that "slow path" (implying a fast path somewhere) that is typical of JIT compilation, we don't have that shit in statically typed functional languages. The "slow path" is already fast, since it doesn't perform any test at runtime!

Re: Why Go Is Not Good

#353

So he wants Haskell. Haskell already exists and has all the features he wants. He should have written his blog in Haskell, but he didn't, and I know why: because a language, which throws all these features together is no longer a practical language. He only sees the benefits of features, not the cost they introduce.

Hindley-Milner inferrence, operators-as-functions, and certain other features, I guess I can see arguments against (although I think they're overstated). However, I don't see any reason why generics, no null pointers, pattern matching, and certain other features would be problematic, let alone not be useful, in a language like Go. I'd be curious as to hear your justification of the claim that "a language, which throw…

I do think that Meijer and Griesemer agree somewhere in this intervew that generics are hard to get right (co and contravariance) and that forgoing generics is a valid design choice: http://channel9.msdn.com/Blogs/Charles/Erik-Meijer-and-Rober... It's been a while and might have been another interview tough.

Re: Why Go Is Not Good

#354

We've seen this same article re-written countless ways. Seriously, this is (intentionally or not) a rewording of every existing criticism of Go, by people who complain that it isn't a language that it isn't. No, Go's solution to generics is not interface{}. The moment you say that, you have lost . You are trying to fight Go and make it a language that it is not. Always remarkable that such critiques always focus on t…

> Always remarkable that such critiques always focus on the utterly trivial, while absolutely ignoring things like concurrency or composing complex systems. But generics are a fundamental tool to solve concurrency or composition. How do you propose to compose complex systems when you can't abstract on the type? How can you add new concurrency constructs that work safely for every type without generics?

Actually Go interfaces map pretty well to a concurrent (and likely networked environment). It's often straightforward to put a network-based implementation behind a Go interface type. When was the last time you saw a web service that is parameterised by a type?

Re: Why Go Is Not Good

#355
post #288
post #262

Earlier quoted context omitted.

I'm writing a language in Go. It is fun. Sum types (and ASTs) are implemented with interfaces which provide a pretty clean and type safe way of doing this.

Can you show some small example encoding of an AST in Go?

http://golang.org/pkg/go/ast/

Well, not that small, i guess :-)

Re: Why Go Is Not Good

#356
post #117

Earlier quoted context omitted.

>Go makes the cost of generic code explicitly visible. Generics encourage over-generalizing behavior that runs counter to writing highly performant code. I think you may be missing some info regarding generics in Rust and Haskell. As I mentioned in the article, there is zero runtime overhead for generic programming in Rust and Haskell. Zip. Zilch. Nada. That's why their constraint-based static generics system is awes…

Please correct me if I am wrong about boxing in Rust, but doesn't boxing produce some overhead, by creating extra heap allocations (and therefore possible memory fragmentation and almost certainly poor cache locality), as well as pointer dereferences? I really hate it in Java when I need an array of bytes but don't know the size in advance, or the size changes, and I have to incur all the cost of boxing those bytes u…

Try reading this: https://gist.github.com/Kimundi/8391398.

Re: Why Go Is Not Good

#357
post #277

Earlier quoted context omitted.

There's no question that Rust and Haskell have better tools than C++ for abstracting code. Go is just demonstrating that you can write great software without the aid (and cost) of generics.

Is there demonstrably great software written in Go yet? I've seen some people using it but I've yet to see a "killer app" (the way e.g. MLDonkey convinced me I should take OCaml seriously, or Pandoc convinced me I should take Haskell seriously).

A few spring to mind. Such as Docker and large parts of Google and CloudFlare.

However I think your benchmark for a language's worth is a pretty superficial one.

Re: Why Go Is Not Good

#358
post #26
post #3

This was a good read. Can anyone comment on whether they find the problems outlined in the article to really be painful in day-to-day go development? From my initial dabblings with the language, it feels like its constraints may not actually be a big deal in practice, and may even be more of a help than a hindrance in large projects. It would be nice to get some commentary from more experienced go users.

I would not say that I am particularly experienced, but I will tell my point of view from a not particularly sophisticated programmer. I am interested in seeing what objections others may have to what I write. Compared to other popular programming languages aimed at web programming, such as Python, Ruby and PHP, Go provides more type safety. Comparable to Java's but for less code. Go's runtime and development tools a…

Python may be popular for web development, but that's not even it's most dominant field. I haven't even heard of any clear winner.

Re: Why Go Is Not Good

#359

Earlier quoted context omitted.

Hindley-Milner inferrence, operators-as-functions, and certain other features, I guess I can see arguments against (although I think they're overstated). However, I don't see any reason why generics, no null pointers, pattern matching, and certain other features would be problematic, let alone not be useful, in a language like Go. I'd be curious as to hear your justification of the claim that "a language, which throw…

I do think that Meijer and Griesemer agree somewhere in this intervew that generics are hard to get right (co and contravariance) and that forgoing generics is a valid design choice: http://channel9.msdn.com/Blogs/Charles/Erik-Meijer-and-Rober... It's been a while and might have been another interview tough.

I think D got generics right.

Re: Why Go Is Not Good

#360

I also don't get why the for-loop uses a "range" keyword at all, isn't that what typing is for, can't it just figure out that the type is enumerable? I like most of Go so far, but interface{} is possibly the ugliest artifact of a programming language that I've seen, next to pretty much all of c++ Rust and Go should have a baby

May be D will interest you.
Post reply on HN