Hacker News new | past | comments | ask | show | jobs | submit login
How Go improves expressiveness without sacrificing performance (cheney.net)
49 points by luriel on Feb 11, 2012 | hide | past | favorite | 17 comments



I am not convinced that this has anything to do with Go improving expressiveness. If anything, this seems more like whichever Go compiler is being used is not doing common subexpression elimination, and that is forcing the developer to re-invent a 'map' that returns nothing but mutates the list in place, albeit in an unusual way.

What are these "improvements" in expressiveness being compared to? Certainly not C or C++, as the initial problem isn't an issue, and the proposed solution is possible.


I think the improvement in expressiveness here is in not having to do &E before calling the method that has receiver type * E. That is, (&E[i]).update(1, 2, 3, 4) and E[i].update(1, 2, 3, 4) do the same thing, so he was able to eliminate writing &E[i].

Also, if the method was defined with receiver type E, and you have a variable x of type * E, you can also do x.update instead of (*x).update. Go automatically dereferences.

(edited: my asterisk operators made everything italicized)


Can anyone explain why BenchmarkUnroll was specifically set to run twice as many iterations as the other two for the timing tests? It seems intentional. But why? Is there some overhead in having the compiler unroll the code versus manually that required more iterations to "even out"?

   BenchmarkUpdate 500000 2996 ns/op
   BenchmarkManual 500000 4642 ns/op
   BenchmarkUnroll 1000000 2824 ns/op


Can the optimizer not eliminate the redundant bounds checks in the "good idiomatic" version?


Check the first comment in the article - I can't believe that is actually good and idiomatic. The author uses the indexes, but the range command also supports returning the values.

To be fair, I have a lot of difficulty figuring out what's a reference and what's a value in Go; I suspect if it were an int and not a struct, that wouldn't work.


Only slices, maps, and channels are reference types.


Go syntax makes me cringe. example:

> for i := range e {

> var e = make([]E, 1000)

It's confusing and against mainstream conventions for no good reason.


That's a common thought from anybody who first looks at Go code. But when you play around a little you realise that all these sharp syntax constructions happen to increase pragmatism, they are well-thought to make the coder happy.

I think that Go syntax falls into something like an uncanny valley —so similar to C-like languages that you instinctively compare it to them but just so different that it feels weird at first. But you'll love it.


Worth a read, if you find go's syntax confusing: http://blog.golang.org/2010/07/gos-declaration-syntax.html

However, its true, I also don't like the :=, or []type syntax purely for aesthetic reasons, but I can see at least the reasoning for it.

As the article points out, the * syntax is oddly non-uniform which it kind of inherits from c. So it's a mixed bag.

Overall though, I find the syntax is less of a problem when you have a big block of go code and you can see it all working together.

It's when you get these little fragments that it looks a bit odd, compared with what you might be use to.


I find that most programming languages have confusing syntax that go against mainstream conventions for seemingly no reason. As might be expected from Bell Labs alumni, most of Go's design decisions have good reasons.


What is confusing there and/or against "mainstream conventions" (whatever those are)?


If you don't know Go and you look at this 'make([]E, 1000)'. What does it tell you? How about this 'make(map[string]int) or make(chan int) ?'

for i := range e {

Why bring back := from pascal family and steer away from common conventions? Why range doesn't take parenthesis while make does?

Also trying to mix dynamic + static type languages will add to the confusion. Deference pointers in a language that looks dynamic but acts static is not mainstream.


There is a reason why it is Go and not the Google C Compiler(They could call it GCC so we don't even have to learn a new compiler name it would be great day for not changing anything). If it were identical to C what would be the point really?

Incidentally a := 5 is a short hand for the Cish int a = 5; = is still general assignment. The extra colon causes a variable declaration with type inference.

If you don't know Go and you look at this 'make([]E, 1000)'. What does it tell you? How about this 'make(map[string]int) or make(chan int) ?'

I don't know Go 'make([]E, 1000)' My take is it is making something maybe even 1000 of them. make(map[string]int) It is making a hashmap with strings and ints, probably with strings being the key and ints being the value. make(chan int) It is making a chan int whatever in the heck that is.


Do you know what := does in Go? What "common conventions" provide the same concise expressiveness?

As for your complain about make(), what does it have to do with syntax?

Why doesn't range require parens? Among other things because it has no need for them, while make() clearly does need them.


> Do you know what := does in Go? What "common conventions" provide the same concise expressiveness?

I know what := means because I have a Pascal background, most programmers are used to = as being the assignment operator. But the mere fact that you asked me what ":=" means proves my point. It's not common and you don't expect everyone to know it.

Why range doesn't require parenthesis? It takes parameters just like make does.


"I know what := means because I have a Pascal background"

But it's not the same: in Pascal := means assignment, whereas in Go it means variable declaration. Go uses = for assignment, as is the popular convention.

You must learn new things when you learn a new programming language. People should stop being surprised and/or upset by this. Besides, Go's syntax is not all that shocking or unusual, especially compared to Scala, Erlang, or Haskell. I regularly switch between Go, JavaScript, C, and Python and don't have any trouble adjusting.

"Why range doesn't require parenthesis? It takes parameters just like make does."

Range is a keyword, while make is a function. Range is used with a single value (the map, slice, or channel being ranged over), while make may take up to three arguments.

Please - it is really silly to critique the syntax of a language if you don't know the language.


:= in go means "declare this variable and infer it's type"

You can always use i E = range e or similar, also range is not a function, it's part of go's syntax and always takes one argument. You don't need parens for the unary - operator.

Go does have different syntax from most C derived languages, but the differences are there for a reason. You need to learn any language to understand it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: