Most active commenters
  • NateDad(6)
  • meowface(5)

←back to thread

131 points apta | 17 comments | | HN request time: 0.609s | source | bottom
1. ereyes01 ◴[] No.9266715[source]
If I wasn't already a Go programmer, reading this would make me more interested in Go than not.

Simplicity is deceivingly challenging, and quite different from simple-mindedness, which seems to be what the author is accusing Go of being.

Keeping code simple, elegant, and consistent is IMHO one of the most valuable principles a team can adhere to. Simple is not necessarily shorter, as short can often be subtle and sneaky rather than simple. Complex power tools can be fun to the inquiring mind, but the ultimate consumers of your product almost never appreciate how you built it, but almost always appreciate the final outcome.

A wise man once said: “Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian Kernighan

replies(2): >>9266740 #>>9271681 #
2. meowface ◴[] No.9266740[source]
There's also the argument that your chance of writing buggy code increases with each additional line you write.

Highly readable code helps reduce bugs. But if that code is also so simplistic that it necessitates a lot of verbosity, you definitely increase the chance of introducing some stupid bug. Thankfully, as a compiled language, Go can find a decent portion of the silly stupid bugs where in a more expressive language like Python they might go hidden for longer, but it's still a big tradeoff you're making.

replies(2): >>9267290 #>>9267710 #
3. NateDad ◴[] No.9267290[source]
Go is not significantly more verbose than python except in a couple trivial cases (list comprehensions become a 3 line loop). Across even a moderately sized program, this will most likely not even amount for a statistically significant difference.
replies(2): >>9267691 #>>9268256 #
4. meowface ◴[] No.9267691{3}[source]
As a professional Python developer and amateur Go dabbler, I very vehemently disagree.

Without access to list/dict/set comprehensions, or libraries like itertools, or a lightweight lambda syntax or something like Ruby's blocks, transformations on collections will always be considerably more tedious and verbose.

Various functions have "bring-your-own-buffer" calling conventions, which will often double or triple the number of lines required for those function calls.

No tuple unpacking, no ability for functional programming (Python's isn't that amazing but with functools and some of the builtins, you can get pretty far), no operators for string formatting or anything but absolute barebones operations.

Combine that with what Go lacks even compared to languages like Java (no inheritance [which is usually an anti-pattern but does decrease verbosity when used properly], no generics, no deep type/class reflection) and it's hard to say that Go isn't a verbose language.

No statically typed language is going to be as terse or expressive as Python can be.

replies(1): >>9275439 #
5. ereyes01 ◴[] No.9267710[source]
This topic we're debating is very well studied. There's lots of good research out there that attempts to correlate how predictive certain attributes of code are to future bugs. Here's one paper in particular that is a very good read and widely cited: http://research.microsoft.com/pubs/70232/tr-2005-149.pdf

As you would imagine, doing this is quite hard, and quite inconsistent from project to project. Lines of code may bear some correlation to future bugs in code for some projects and languages, but it's far from clear cut that more lines of code == more bugs or more complexity.

replies(1): >>9267755 #
6. meowface ◴[] No.9267755{3}[source]
Thanks, that clears up some misconceptions I had.
7. Paddy3118 ◴[] No.9268256{3}[source]
Go does seem more verbose than Python. Rosetta code tries for idiomatic solutions to common tasks, here's one such completed in both Python and Go: http://rosettacode.org/wiki/Bitcoin/address_validation

You would need to know the nature of the tasks to pick out those that need longer answers but all the Go tasks are here: http://rosettacode.org/wiki/Category:Go - most of which should have Python solutions.

replies(1): >>9268763 #
8. NateDad ◴[] No.9268763{4}[source]
Most of those programs are trivially small, and often consist mostly of transformative loops. Yes, go will be worse than python for that. But in a real project, the difference will be minimal, a few percent, which will be lost in the noise of the specific implementations, tests, etc.
replies(1): >>9272654 #
9. lectrick ◴[] No.9271681[source]
How will you keep your code simple with all those manual error checks?

How will you keep your code simple if your procedural bent causes you to create dependencies/coupling at will?

How will you keep your code simple if your variables are mutable?

Recipe for complexity and bug hell

replies(1): >>9275419 #
10. Paddy3118 ◴[] No.9272654{5}[source]
Even so, Go seems less succinct in comparison on several tasks. Such differences will most likely be magnified in larger programs.
replies(1): >>9275401 #
11. NateDad ◴[] No.9275401{6}[source]
an example from https://www.spacemonkey.com/blog/posts/go-space-monkey -

we decided to transliterate our 90k lines of Python directly to Go, line by line

The 90K number includes our tests, but without tests, the Python codebase is 36,784 lines of code. Those same lines of code became 41,717 lines of Go code. So, not that much of an increase. When you consider that's just 4,933 more lines, it's not crazy to assume most of those are closing braces.

I'd say closing braces and trivial expansions of list comprehensions into 3-5 line loops.

replies(1): >>9280048 #
12. NateDad ◴[] No.9275419[source]
manual error checks are no more complicated than any other code that branches.

Implicitly fulfilled interfaces make it trivial to decouple code, because I can pass a type to a function in a different package, and that package doesn't even need to know that type exists.

You're obviously pushing the pure functional route, which is nice, but 95% of code in production is procedural. There's a reason for that. I could speculate why, but I don't need to.

replies(1): >>9278532 #
13. NateDad ◴[] No.9275439{4}[source]
Can you explain how tuples are significantly different from multiple returns in real programs? You can do

    func foo() (string, int, bool) {
        return "one", 2, true
    }

    func bar(s string, i int, b bool) {}

    bar(foo())
replies(1): >>9279398 #
14. lectrick ◴[] No.9278532{3}[source]
> I could speculate why, but I don't need to.

I will. There's a pattern out there and it goes something like this:

1) Most programming classes still teach procedural

2) New, typical real-world programmer looks at procedural and functional, finds functional more alien and difficult (because it's far more dissimilar to the popular languages s/he played around with in their youth), settles on procedural

3) 10 years later, after spinning a significant percent of wasted cycles on piles of procedural spaghetti code and spending hours debugging classes of bugs that ended up coming down to a lack of managing complexity, various interdependencies, no recognized schedule to pay down difficult-to-quantify technical debt, and mutability... programmer looks at functional languages again and finds them not lacking

4) programmer takes on a side project in a functional language, thinks it's awesome, mind is bent in pleasant shapes, considers quitting day job or "the big rewrite", realizes the latter is not feasible (see: Joel Spolsky), gets frustrated with the status quo

5) programmer posts to future incarnation of Hacker News probably sounding like an ivory-tower prophet, preaches about macros and homoiconicity and immutability and the dynamics of programming teams, ends up angel-investing and founding an incubator instead of fighting the hopeless procedural-vs.-functional battle

6) Repeat.

;)

EDIT: BIAS: I think Elixir (http://elixir-lang.org/) finally has a real shot at breaking this cycle. It's the first functional language I've used that "felt" accessible enough to most folks (Ruby-ish syntax) AND has all the typical functional niceties AND has real macros without being jarringly off-puttingly homoiconic AND has an extreme focus on concurrency (perfect for the future Web... it can fire off a million PID's in a second) AND it embraces failure (good for anything that touches "the real world") AND uses the Actor model (a candidate for "most scalable language design pattern"). OO is, IMHO, dead man walking right now. It's too easy to pass mutable state around everywhere, it complexifies code too much by allowing any code anywhere with an instance of a class to call methods on it (therefore coupling the class implementation to the entire codebase), it doesn't realize the cost of inheritance, it is difficult to parallelize, etc. etc.

15. meowface ◴[] No.9279398{5}[source]
When dealing with function calls, they're roughly the same.

But how about things like:

    g = some_input() # A list with 3 elements
    a, b, c = g
Or in Python 3+:

    lst = [1, 2, 3, 4]
    head, *tail = lst # 1, [2, 3, 4]
    *init, last = lst # [1, 2, 3], 4
    a, *b, c = lst # 1, [2, 3], 4
replies(1): >>9288538 #
16. meowface ◴[] No.9280048{7}[source]
That's definitely interesting, but I'd have to see both codebases to make any real determination. It's plausible their Python code was extremely imperative, overly complex, and/or not idiomatic.
17. NateDad ◴[] No.9288538{6}[source]
You can do that in go with just a few more characters:

    g := some_input() // A list with 3 elements
    a, b, c := g[0], g[1], g[2]
I'll grant you, having to specify the indices is slightly more verbose, but it's also a lot more clear... because what happens when g has more or less than 3 elements? In Go it's clear, more is ok, less will get you a panic.

    lst := []int{1, 2, 3, 4}
    head, tail := lst[0], lst[1:]
    init, last := lst[:len(lst)-1], lst[len(lst)-1]
    a, b, c := lst[0], lst[1:3], lst[4]
Again, I don't think the magic unpacking is really helping that much... doing it the same way you'd do anything else in Go is slightly more verbose, but it's also not some new syntax you have to figure out either.