Hacker News new | ask | show | jobs
by YcombRegBroken 4733 days ago
Round 4 of these tests is what triggered my dive into Go this past month, and it has been a revelation. If you add in the concurrency capabilities, the language simplicity, and nice balance between overly terse syntax (Python one liners...) and overly verbose typed languages (Java), the whole package is even more impressive.

The only real thing I think it is missing is a "high productivity" application framework like Rails to elevate it from "damn, I'm impressed" to "it would be ill advised to use almost anything else".

</reluctant fanboy rave>

3 comments

Have you tried modern ML-style languages? e.g: Haskell, OCaml, F#?

They also combine the nice conciseness of Python, with great concurrency (better than Go) and a lot more safety (less late night crashes).

With respect, and I say this having experimented with Haskell, OCaml, any many other functional languages as well, just, no. Those languages come at a MUCH higher mental cost than go. Go is wonderful because writing it doesn't feel like I'm attempting a CompSci doctoral thesis. I can also say I have yet to see the Go runtime crash, and I am using in production.

I also challenge your "better concurrency" claim.

What do you mean by "mental cost" here? Cost of initial learning? Then I agree... But learning a language is an O(1) cost that takes a few weeks to a few months. We program with the language for many years.

I never said the Go runtime will crash, but your programs will, because of unsafe nullability, mutability in the concurrently shared state, and various other problems in Go.

Better concurrency in Haskell: In addition to having light-weight threads like Go and channels like Go, Haskell also has software transactional memory which Go lacks. Haskell also has `par` annotations on pure expressions that allow parallelization with guaranteed lack of effect on program semantics. Haskell also has data parallelism.

Haskell (and most of the other languages mentioned) is exceptionally clever. This, above all else, is it's downfall. For me, especially when tasked with building a high productivity development team, clever code is a ticking time bomb. It's easy to write, but hard to maintain and modify. It requires more mental ram to analyze any given piece of code, and is much more difficult for multiple programmers to contribute to. It's tiny, to be sure, but, again, I think that is negative, not a positive. Maximum clarity is not minimal code.

Go, on the other hand, is not clever. It's boring as hell, honestly. This is a Very Good ThingĀ® when it comes to building out a dev team, and I feel, the single biggest reason Google put the resources into creating it.

As for the crashing, of course I see some dangerous areas. Educating developers on avoiding a small regions of pitfalls is much easier than managing a team of clever coders though.

I disagree that Haskell is "clever". I think Haskell is "smart".

Using "Maybe a" when you have a nullable value is smart, not "clever". It aids maintenance and readability, not hampers it.

Using pattern matching is the same.

Haskell builds on mathematicaly simplicity, which makes things hard to grasp at first. This may be mistaken for cleverness.

Unless I'm misunderstanding you -- can you give an example of something clever in Haskell?

I'm not a haskell expert (obviously), but the time it takes me to parse things like this is time I would rather spend reading 5-10x the number of lines and getting the meaning right away.

  let loeb x = fmap ($ loeb x) x in 
  loeb [ (!!5), const 3, liftM2 (+) (!!0) (!!1), (*2) . (!!2), length, const 17]

(btw, I have no idea what the hell this does. Something to do with spreadsheets, apparently. I found it on http://www.haskell.org/haskellwiki/Blow_your_mind, which has enough cleverness to make me want to cry)

I've seen cleaner and more readable code in production haskell, but this sort of thing happens enough that I'm very cautious.

I would go so far as to say Haskell is better.

But, then you gotta remember, "worse is better" (New Jersey style), and Go is worse. New Jersey style: (1) be simple in both implementation and interface (2) correct, be correct as long as it doesn't make it more complicated, simple is more important than correct (3) consistent, when you can be consistent, do be, but simplicity is more important and (4) completeness, be as complete as you can, but realize completeness can be sacrificed for any other objective.

I think C and Go share a lot of New Jersey style -- Go is great in simplicity (remember simple isn't easy). I think Go will continue to go quickly because of these attributes.

> I never said the Go runtime will crash, but your programs will, because of unsafe nullability, mutability in the concurrently shared state, and various other problems in Go.

Personally, these problems are not what are a time-sink for me. The problems that I spend a vast majority of my time on tend to fall into two categories.

First, there are design problems. i.e. how do you model your data to be queryable, how do you architect services to make them resilient to machine failure, how do you monitor services, how do you route logs, etc. With these problems, Haskell doesn't help here. Go doesn't help here either.

Second, there are operational problems. i.e. your FS might randomly corrupt some data you stored previously (remember to checksum), your caches might get out of sync (fun problem if you ever go multi-DC), your service has shoddy backoff and DDOS's a failing downstream service, etc. With these problems, Haskell doesn't help here. Go doesn't help here either.

Am I saying that there's no value to the fact that Haskell solves these at compile time? Of course not. Just that the relative amount of time that would save for me is not my deciding factor when picking a programming language.

Another way to think about it is that people have (I include myself in this category) written large-scale projects in dynamic languages which have all the problems you mentioned plus a few more. And yet, the developers at Twitter, or Facebook, or Reddit don't spend the vast majority of their time face-palming at type-errors or NPEs, or ConcurrentModificationExceptions. They have other concerns.

I think people tend to underestimate the amount of time they spend on problems, when those are uninteresting. A single null dereference error may be trivial to fix, but the overhead around fixing any bug may be costly. For example, you might need to deploy a whole new version, rerun test suites and have a bunch of meetings. Then after all of this, you might remember that the problem only costed you 10 minutes of fixing the bug.

When you implement a red-black-tree, do you not spend any time testing your invariants? Or figuring out the bugs? That's a good example of where the Haskell type system can simply give you compile time guarantees saving you from bugs and from having to test them.

I also worry about the problems you mention, many of which Haskell indeed doesn't help much with. I don't see how these problems (which you solve once, usually by reusing a library) are what costs the majority of the time. A big, non-trivial implementation has bugs and will require testing. Haskell will have less bugs, and require less tests. This is a pretty big deal.

It's weird that you bring Twitter as an example, as they canned a dynamic language solution for a static language that is in many ways very similar to Haskell.

I've seen multiple large scale projects in dynamic languages. They all fail to scale well, both performance-wise and maintenance-wise. Statically-typed systems scale far better along both of these axis.

> I think people tend to underestimate the amount of time they spend on problems...

Again, the implication is that people who use languages with looser type-systems than Haskell spend lots of time dealing with the problems that you mention. In my experience, that is not the case. You can claim that I'm underestimating the impact of such bugs if you'd like.

> When you implement a red-black-tree, do you not spend any time testing your invariants?

Testing is, as far as I can tell, the reason that these problems don't come up. In the process of solving all of those problems I listed above, you tend to write a bunch of tests that exercise the same code that is run in production.

> It's weird that you bring Twitter as an example, as they canned a dynamic language solution for a static language that is in many ways very similar to Haskell.

I assure you that this transition is far less complete than you might think, and even when complete, will have more Java than Scala. Note that both of these languages allow shared mutable data, both allow null pointers.

> They all fail to scale well, both performance-wise and maintenance-wise. Statically-typed systems scale far better along both of these axis.

Oh, I agree. Go is statically-typed. However, you're advocating going even further along the spectrum, and I'm saying that going further brings diminishing returns, and starts costing you in terms of available engineers, and your productivity in writing code. I think Go occupies a good point along this spectrum, where I can write robust code without arguing with a compiler.

I'm a little confused here. You realize that Go is also statically typed, right? I'm not sure where any debate about dynamic languages started. The points you make about static vs dynamic are valid, just not relavent at the moment.

It's funny, too, how you talk about "implementing a red black tree" like it's an everyday occurrence. I'm guessing you are a teacher/researcher (in which case this entire discussion makes much more sense). On any application team I've worked with (in the valley or out), implementing a binary tree from scratch would require extreme justification and literally have to be the only way possible to solve the problem.

I can't remember the last time I implemented a data-structure in a web framework. You just use the built in dictionary/hash table and get on with life.
I think you are vastly under-estimating the learning cost. We're talking about teams of developers, not a hobby project. A few months * multiple programmers adds up to man-years really quick.

Go is much simpler. We deployed our first production (admittedly a fairly minor piece) Go service under a week after we made the decision to start using Go.

PS: State is only shared when you make it so. Go concepts like channels make it very easy to write, _and debug_ clear, decoupled non-trivial parallel code.

If you have to pay the salaries of programmers for the next 3 years to develop some solution, and know that 10% of that time will be spent learning a new technology that will make them 20%-50% more effective for the remaining 90% of the time. Would you do it or avoid it, based on the large cost of 10% of these programmers' time?
When I have another solution that will make them 30% more effective with only a 1% learning cost, yes!
No way in hell OCaml has "better concurrency than Go". Go is built around the concept. Not that OCaml is not an awesome language though, but that's just an outlandish statement.
You're right, I was thinking more of Haskell in the concurrency part.
Since you are replying to this in the Haskell thread - Go clearly performs FAR better than Haskell on these simple benchmarks.

So as far as I can tell, the pros of using Haskell over Go would be

1) More safety from crashes

while the Cons of Haskell would be

1) Slightly slower than Go at HTTP

2) Far, far slower than Go at database queries

3) Much steeper learning curve

4) Based on the history of ML languages, will never be popular. Go is gaining popularity quickly.

I think recommending Haskell to someone for a real project is bad advice from the above. Recommending Haskell to someone for self enrichment is another story, and I can get behind that one.

1. More safety from bugs in general, not just crashes. Haskell programs will generally be more reliable than Go programs.

2. If you look at the Benchmarks game, you will actually see that Haskell beats go there.

I think this benchmark is far narrower than the Benchmarks game and is thus less representative.

3. shouldn't really be a serious consideration for a career programmer (weeks to a couple months of learning to be more effective for years to come is a no-brainer).

4. is untrue, Haskell has already gained more popularity than the ML languages had in the past. And so is F#.

how about http://robfig.github.io/revel/ ? I just skimmed thru their manual and it seems quite promising
I was just looking at Revel too. But from the homepage:

Development Status: Early adopters only. Pull requests welcome. Development is closing in on the "final" 1.0 design, but the rate of change is still high. Expect to get your hands dirty.

Wouldn't quite appeal for people looking for a Go based Rails yet, but I would have to agree.. it does look very promising.

Revel is pretty great so far (I actually just made my first contribution yesterday!). Some important things it needs though: support for HTTPS, better DB support (some type of ORM, although gorp is sufficient for now), HTTP auth, and better template engine (currently uses the built-in Go "template" package which is meh). Those are the major things that come to my mind.
I disagree with ORM, at least as a "need". Why go to the trouble of migrating to a much higher performance platform to just give most of that performance back?
That's actually very true. I pulled that one off of the GitHub page though. I believe its something robfig wants (at least optionally) for when it's deemed production-ready.
Check out https://github.com/jasondelponte/gokart - Rails style development with go. "The gokart gem by default combines SASS, Coffee Script, Rake, and Sprockets with Go to provide a great development environment. This environment supports test driven development (TDD) with ruby guard and jasmine. There are no external dependencies other than Go and ruby (which I expect you already have...)"