Live data from Hacker News

Why Go Is Not Good (2014)

yager.io

141–150 of 466 posts

Re: Why Go Is Not Good (2014)

#141
post #37

While many of these points (on generics especially) are completely legitimate, this article will fall on deaf ears. My impression of the Go community (both within Google and outside of it) is that there is a very ... moralistic? .... sense of "You don't really need that, we know best" going on. It aims to be a pragmatic language. But IMHO the anemic nature of the type system is a practical handicap that they have mad…

that's kind of what happens when you take some of the brightest minds that hacked on Plan9 and Inferno for years and have them build a programming language. It's going to be unique. Idealistic. Romantic. reading many of the points here makes me think: alienated java user who doesn't like change

How do you get "alienated java user who doesn't like change" from a post whose author is obviously well versed in Haskell, Rust and Go?

Re: Why Go Is Not Good (2014)

#142
post #41

Earlier quoted context omitted.

Could you go into more detail about why operator overloading enables generic functions in a way simple functions don't? I don't see it.

Without operator overloading, it's hard to make generic numeric algorithms palatable. Compare (fake Go-with-Swift-generics syntax): func Distance (x N, y N) N where N Number { return x.Mul(x).Add(y.Mul(y)).Sqrt() } Versus: func Distance (x N, y N) N where N Number { return Sqrt(x * x + y * y) } If your reaction is "well, Distance doesn't look too bad like that", I can replace it with matrix multiplication or point-in…

Of course, you frequently don't want operator overloading for matrix multiplication. Avoiding allocations is a big deal for speed, and so c.Mul(a,b) is often the right answer even with operator overloading.

Re: Why Go Is Not Good (2014)

#143

Earlier quoted context omitted.

func SameSideOfTriangle (p0 Point2D , p1 Point2D , a Point2D , b Point2D ) bool where N: Number { ba := Point2D(b.x.Sub(a.x), b.y.Sub(a.y)) p0a := Point2D(p0.x.Sub(a.x), p0.y.Sub(a.y)) p1a := Point2D(p1.x.Sub(a.x), p1.y.Sub(a.y)) cp0 := ba.x.Mul(p0a.y).Sub(p0a.x.Mul(ba.y)) cp1 := ba.x.Mul(p1a.y).Sub(p1a.x.Mul(ba.y)) dot := cp0.x.Mul(cp1.x).Add(cp0.y.Mul(cp1.y)) return dot >= 0 } Versus: func SameSideOfTriangle (p0 Po…

I didn't mean to imply that it is never useful, just that it's not worth the baggage in my experience. Genuinely asking: Why does this function need to be generic over Numbers? Couldn't you implement it once or twice for whatever actually-numeric types you need? How many different Point2D template instantiations do you actually have?

My experience from graphics programming is that, yes, this is a subdomain where you want both the ability to shorten your functions with overloading and the ability to make your underlying types dynamic. There's a lot of fiddly-bit optimization in that space that is both necessary and much easier to do if you can transition quickly and smoothly from one type to another without having to boil an ocean of declarations.

Granted, you then have the problem of having to deal with overflow on different types, but that's just one of the ocean liner of problems you've signed up for if you're working in the graphics space. May the odds be ever in your favor. ;)

Re: Why Go Is Not Good (2014)

#144

Earlier quoted context omitted.

Without operator overloading, it's hard to make generic numeric algorithms palatable. Compare (fake Go-with-Swift-generics syntax): func Distance (x N, y N) N where N Number { return x.Mul(x).Add(y.Mul(y)).Sqrt() } Versus: func Distance (x N, y N) N where N Number { return Sqrt(x * x + y * y) } If your reaction is "well, Distance doesn't look too bad like that", I can replace it with matrix multiplication or point-in…

Of course, you frequently don't want operator overloading for matrix multiplication. Avoiding allocations is a big deal for speed, and so c.Mul(a,b) is often the right answer even with operator overloading.

How does allocation relate to operator overloading?

Re: Why Go Is Not Good (2014)

#145
post #61

Earlier quoted context omitted.

Using go for goroutines and channels is a bit like using Perl for regular expressions. The features have been added in a way that makes them easy to use and serves as a nice idiomatic platform, but fundamentally it's functionality other languages can provide via library support.

+1 on this. Clojure's core.async[0] is the perfect example of an implementation of CSP as a library. Even JS can be used to implement such concepts via the use of generators[1]. [0] https://github.com/clojure/core.async [1] https://github.com/ubolonton/js-csp

I used to feel this way until I realized the limitations of core.async. In Go I don't have to worry about whether the particular functions I'm calling, especially IO-related, are blocking or not, as Go will create new lightweight goroutines as necessary to deal with all that. With core.async, if I use blocking IO inside of a coroutine I risk causing thread starvation. See http://martintrojer.github.io/clojure/2013/07/07/coreasync-a...

Maybe things have changed since 2013, but I feel like this is a fundamental limitation of running on the JVM vs what Go can provide in its runtime.

Edit: Also, it appears to be much easier to simply "run out" of Clojure coroutines than Go goroutines, but perhaps that's also changed. Anyways, my point is that by core.async operating as a macro you still can't overcome limitations of the underlying runtime, whereas Go's runtime was purposely-built to support goroutines.

Re: Why Go Is Not Good (2014)

#146

While many of these points (on generics especially) are completely legitimate, this article will fall on deaf ears. My impression of the Go community (both within Google and outside of it) is that there is a very ... moralistic? .... sense of "You don't really need that, we know best" going on. It aims to be a pragmatic language. But IMHO the anemic nature of the type system is a practical handicap that they have mad…

[deleted]

Re: Why Go Is Not Good (2014)

#147

Earlier quoted context omitted.

func SameSideOfTriangle (p0 Point2D , p1 Point2D , a Point2D , b Point2D ) bool where N: Number { ba := Point2D(b.x.Sub(a.x), b.y.Sub(a.y)) p0a := Point2D(p0.x.Sub(a.x), p0.y.Sub(a.y)) p1a := Point2D(p1.x.Sub(a.x), p1.y.Sub(a.y)) cp0 := ba.x.Mul(p0a.y).Sub(p0a.x.Mul(ba.y)) cp1 := ba.x.Mul(p1a.y).Sub(p1a.x.Mul(ba.y)) dot := cp0.x.Mul(cp1.x).Add(cp0.y.Mul(cp1.y)) return dot >= 0 } Versus: func SameSideOfTriangle (p0 Po…

I didn't mean to imply that it is never useful, just that it's not worth the baggage in my experience. Genuinely asking: Why does this function need to be generic over Numbers? Couldn't you implement it once or twice for whatever actually-numeric types you need? How many different Point2D template instantiations do you actually have?

[deleted]

Re: Why Go Is Not Good (2014)

#148
post #121
post #95

Earlier quoted context omitted.

I think some of that stems from the fact that the arguments against Go are often over emphasised matters of personal preference, or just so frequently raised that it becomes tiresome to read. I love Go. I know it's an imperfect language and because of that I do often hate specific Go idioms. So I definitely don't have a "bunker mentality" when it comes to Go; nor any other language. But in terms of "getting stuff don…

In the end there is no one true best language out there. Go is great for a subset of problems and making it better at other things is a balancing act. The most popular languages are generally accidents of history. Unix gave us C, browsers gave us JavaScript, and Databases gave us SQL, etc.

I don't really see how Go is, or should be, that limited as a factor of design (in contrast with something like Erlang). It's just that everyone in the ecosystem is focused on on the same things and when people with other use cases, that could benefit from the properties of the language, try to make themselves known it's all "works for me".

Edit: Thanks for proving my point everyone.

Edit2: To be slightly less snarky, despite the article I don't see any reason why Go couldn't be a fit for e.g. an oscilloscope which today is running a complete, often multi-core, linux system with 100k+ lines of code (with help from an ADC and FPGA etc. of course). If it wasn't for the fact that few people would undertake such an effort when that would be akin to swimming upstream against the ecosystem.

Re: Why Go Is Not Good (2014)

#150
post #88

Earlier quoted context omitted.

Type 1 defines: .add(x) Type 2 defines: .plus(x) Type 3 defines: .vector_add(x) Now, implement a function 'average' that can work on any of these three types. If you can get everyone in the world to agree to a convention of how to express 'addition', then there is no difference, except we already have a convention for 500 years, and it is the '+' operator. Why you think the '+' operator is confusing but .plus() is no…

Operator overloading is often problematic because the operators come with semantic baggage, such as properties they maintain, and implementations of those operators often don't maintain those properties. For instance, addition is associative, and has no additional side effects beyond the value it produces, but an overloaded operator won't necessarily implement those. Abstractly there's nothing wrong with that, but in…

> Operator overloading isn't really "right" or "wrong" per se, but it's probably a bad idea for anything that isn't able to fully implement the contract of the operator, including "associativity", "no side effects", whether exceptions can be thrown, etc.

Operators are not special here. What you are saying is basically "don't claim to implement the interface if you didn't implement it".

This exact problem exists widely in, for example, Java. How often do you see a Java object where someone overrode equals() but not hashCode()? I've seen that problem vastly more often than anyone doing something crazy with operators.

Post reply on HN