Live data from Hacker News

Benefits of named return values in Go

blog.minio.io

111–120 of 146 posts

Re: Benefits of named return values in Go

#111
post #103

Earlier quoted context omitted.

It doesn't change the behavior of the return keyword, though. It adds a case, but it's an orthogonal case; if you have a function that returns anything, a bare return can only be using the named return values. My position is that I'm OK with saying "only use this if you need to screw with the return values via defer, and thus, the presence of named return values can be reliably inferred to mean that someone is using…

Without a named keyword, a void function can use the return keyword to terminate control flow conditionally. So it's only orthogonal in the case of a function with a typed return value. Which is fine. I have no problem with it. I'm a Haskell/ Clojure/Erlang/TypeScript/CL developer, so I'm used to this. But golang users beat me over the head with the "simplicity" of Go and use examples of Haskell and Clojure having le…

I feel some of the criticisms for this feature are a little exaggerated. I mean comments like "Also my hair gets paler and my body grows weak thinking about using defer with named return values" are borderline silly. Opinions of named returns aside, they're really aren't that hard to follow. Or at least if your function is genuinely that complex that you have a physical reaction when trying to parse a function with a named return then I'd suggest that function needs more refactoring beyond the initial critique.

A few direct counterarguments:

* Named returns doesn't change the nature of the return statement. In fact you can still use return with locally scoped variables even with named returns (example below).

    // This is only an example of overriding the default return.
    // I'm not suggesting people write code like this!
    
    func StrToBool(s string) (b bool) {
        if s == "true" {
            return true
        }
        return
    }
* "often long nature of Go functions" is purely a developer style. I prefer the methodology of breaking functions down to small logical units. Sure sometimes the cleanest code is a long function. But most of the code I write and collaborate with is more around 20 lines or less.

At the end of the day named returns do provide some benefit eg when writing public APIs so other users can see - at a glance - what inputs and what returns a particular function takes. But like any feature in any language, a bad developer will easily find ways to abuse it.

Re: Benefits of named return values in Go

#112
post #107
post #98

Earlier quoted context omitted.

"Are they actually frowned upon? I've been writing Go for a few years now and while I acknowledge there will be blind spots in my knowledge, this is still the first I've heard against using that language feature." /r/golang consensus is against using named values. I disagree with it, but the consensus is there. Or at least I think that at the very least named return values should indicate that someone is doing someth…

> /r/golang consensus is against using named values. /r/golang is a toxic subreddit and I wouldn't take anything said there for face value. Dave Cheney deleted his account there and the go team itself wanted to delete that subreddit. So no, /r/golang represents only /r/golang and certainly not the go community as a whole. /r/golang favorite pass time is to take some piece of code or a library and humiliate its author…

A couple of months ago I had someone on /r/golang taking credit for one of my own projects. I just ignored him and took it as a compliment but now I'm not sure if that's an insult (jk)

Disclaimer: I don't follow /r/golang. I was looking at Github traffic and noticed quite a few requests with Reddit as their refer(r)er.

Re: Benefits of named return values in Go

#113

Earlier quoted context omitted.

Without a named keyword, a void function can use the return keyword to terminate control flow conditionally. So it's only orthogonal in the case of a function with a typed return value. Which is fine. I have no problem with it. I'm a Haskell/ Clojure/Erlang/TypeScript/CL developer, so I'm used to this. But golang users beat me over the head with the "simplicity" of Go and use examples of Haskell and Clojure having le…

I feel some of the criticisms for this feature are a little exaggerated. I mean comments like " Also my hair gets paler and my body grows weak thinking about using defer with named return values " are borderline silly. Opinions of named returns aside, they're really aren't that hard to follow. Or at least if your function is genuinely that complex that you have a physical reaction when trying to parse a function with…

> I mean comments like "Also my hair gets paler and my body grows weak thinking about using defer with named return values" are borderline silly.

I regret my deliberate silliness only reaches "borderline" with you. Do I also need a unicycle. What does it take?!

> StrToBool

Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries not to do.

> But most of the code I write and collaborate with is more around 20 lines or less.

I'm tempted to write a github crawler to work this out. Golang is C-like in that its lack of reuse capabilities incentivize longer functions or copypaste functions.

I'm simply against this kind of context-sensitivity in a language that prides itself on being reader friendly. It's not. Let me rephrase my argument.

Question:

   return a; // What does this do?
Response: It returns the value at a. I don't know what that value is, but it must be a local or a function parameter. This function definitely returns a value, one value.

Question 2:

   return; // What does THIS do?
Response: Well... all I can say with confidence is that this returns, the functions execution will end. But I can't tell you if it returns nothing, or a value, or how many values.

The existence of this makes bare returns much more confusing than... well... I struggle to come up with a syntactical convention in Golang that can do this. I haven't written Go for reals for 2 years so maybe you have something better.

To me, this is way worse than even the "worst case" Haskell scenarios where your code only makes sense in the context of its caller.

Re: Benefits of named return values in Go

#114
post #6

I normally hate it when people immediately trot out the old "premature optimization" quote, but it really applies here. Please don't go around naming all your returns just because today's compiler happens to generate better code with them. This is a compiler issue that I'm confident will be fixed one day, especially if you do the right thing and file an issue. But by all means, if you're profiling and your inner loop…

I think accusations of premature optimisation might be a little unfair here.

Ignoring the style issues for a second (I'll pick that up later), if I'm looking at some code and there are two equally viable alternative ways of writing it, one of which saves a chunk of memory* or is faster then it's just perverse to choose the path of larger/slower code. I do this with regular expressions/string functions. I see people use regexes a lot, but the tool I reach for first when doing string operations are the built-in string functions, eg. https://golang.org/pkg/strings/#Contains or https://ruby-doc.org/core-2.4.0/String.html#method-i-start_w.... I'm not optimising, I'm just not de-optimising.

Back to the style issue, at this point if you really feel strongly about the way it looks in the editor, or in documentation then I can see why you would choose one method over the other, choosing the less desirable, but theoretically faster code would absolutely be a case of premature optimisation. I personally don't have a particular preference either way however, and feel like the reasons outlined in the style guide are rather fragile. So ultimately, if I pick up some code full of named return values I don't think it would bother me, in the same way that code that uses none, or mixes them where someone thought it appropriate doesn't bother me either.

* There may be benefits other than just disk/distribution size. Many years ago I read about the benefits of small binaries, something relating to CPU caches, though that may be out of date now and I forget the details.

Re: Benefits of named return values in Go

#115
post #71

Earlier quoted context omitted.

It increasingly does. But it's been a process. Go 1.5 was the first self-hosting release, with the Go compiler auto-translated from C to Go. But it was still fundamentally Ken's C compiler in Go syntax. Every release since (Go 1.6, Go 1.7, Go 1.8, Go 1.9) has been cleaning it up and making it more Go like and less C like. Meanwhile, the backend was also retrofitted. Go 1.7 included an SSA backend for amd64 ( https://…

Why does Go not use LLVM? Are there technical reasons to reinvent the wheel, or is it just because LLVM is Apple's pet?

See this answer from Russ Cox: https://news.ycombinator.com/item?id=8817990

Re: Benefits of named return values in Go

#116
I don't understand, through these examples, why the introduction of a name is necessary in order that an empty return statement be used.

The name doesn't even appear in the function. A name that is declared but not subsequently mentioned serves no purpose (or some side purpose/hack).

In the "NoNamedReturnValue" variant, the return type is still declared. The compiler could, from that type alone, infer that "return" means "return a representative default instance of that type".

That is to say, why can't Go programmers just have this:

  // oi name removed:
  func NamedReturnParams(i int) (/* oi */ objectInfo) {

	if i == 1 {
		// Do one thing
		return // wee, allow this anyway!
	}

	if i == 2 {
		// Do another thing
		return
	}

	if i == 3 {
		// Do one more thing still
		return
	}

	// Normal return
	return
  }
Also, why can't the compiler just optimize away the "return Objectinfo {}" statements down to "return", if those really are equivalent.

Re: Benefits of named return values in Go

#117

Earlier quoted context omitted.

Just for what it's worth, the way I'd fix that problem in the compiler would be to implement dead store elimination via global value numbering. With trivial alias analysis, the compiler would be able to detect that the result of the "duffzero" instruction (which I assume is a memset) is always killed by the "duffcopy" instructions and would eliminate it. See this article for how it's done in LLVM: http://blog.llvm.or…

Not my area of expertise and it is yours, but if you eliminate a zero instruction before a copy instruction how can you be sure that doesn't affect other threads? var x Int // Pass x to a thread by reference x = 0 time.Sleep(1000) x = 1

The memory dependence analysis must prove the memory is unaliased, which ensures among other things that no other thread can have a reference to it. Presumably in Go return pointers are guaranteed to be unaliased.

Re: Benefits of named return values in Go

#118
post #114
post #6

I normally hate it when people immediately trot out the old "premature optimization" quote, but it really applies here. Please don't go around naming all your returns just because today's compiler happens to generate better code with them. This is a compiler issue that I'm confident will be fixed one day, especially if you do the right thing and file an issue. But by all means, if you're profiling and your inner loop…

I think accusations of premature optimisation might be a little unfair here. Ignoring the style issues for a second (I'll pick that up later), if I'm looking at some code and there are two equally viable alternative ways of writing it, one of which saves a chunk of memory* or is faster then it's just perverse to choose the path of larger/slower code. I do this with regular expressions/string functions. I see people u…

The issue is that with the string/regex issue, there's a good reason that the string operation should be faster. Maybe a "sufficiently smart compiler" could optimize it in some cases of static regexes, but it's at least complicated. In cases where the regex is dynamically determined, even the sufficiently smart compiler probably can't optimize away the regex.

In contrast, the case in this article seems like table stakes for an optimizing compiler. It's just not eliminating common subexpressions. There's no reason to contort your code around something that should automatically happen.

Re: Benefits of named return values in Go

#119

Earlier quoted context omitted.

I feel some of the criticisms for this feature are a little exaggerated. I mean comments like " Also my hair gets paler and my body grows weak thinking about using defer with named return values " are borderline silly. Opinions of named returns aside, they're really aren't that hard to follow. Or at least if your function is genuinely that complex that you have a physical reaction when trying to parse a function with…

> I mean comments like "Also my hair gets paler and my body grows weak thinking about using defer with named return values" are borderline silly. I regret my deliberate silliness only reaches "borderline" with you. Do I also need a unicycle. What does it take?! > StrToBool Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries…

> Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries not to do.

But like I said before, you're blaming unclear code on the language rather than the developer. It's an optional feature, so don't use it in inappropriate situations.

It's like the whole goto statement argument. Nobody is suggesting we all using goto's just because the feature exists. But very occasionally it does produce cleaner code. Yet you still get an army of evangelists who argue that "goto" should be stripped from every language specification written since the 80s.

I've read a lot of other people's code. Particularly the Go source code itself - there's named returns all over the place there. There are also some quite long and complicated functions too. The use of a named return has had a negligible impact on my ability to parse a function compared to any of the other inherent complexities that function exhibited. ie I followed that code just as easily than if those returns were not named.

Which is why I keep coming back to the "You're points are not wrong per se but they are greatly exaggerated." arguement. But like nearly all arguments about language semantics and syntax, developers love to argue how their personal preferences are conclusive scientific facts. Ironically spending more time trying to prove our points online than we actually spend affected by the problems we're arguing about.

So yes, you are not wrong per se. But you are greatly exaggerating the issue.

Re: Benefits of named return values in Go

#120

Earlier quoted context omitted.

> I mean comments like "Also my hair gets paler and my body grows weak thinking about using defer with named return values" are borderline silly. I regret my deliberate silliness only reaches "borderline" with you. Do I also need a unicycle. What does it take?! > StrToBool Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries…

> Make this function 30 lines long, take 6 arguments and then you have my original argument. It creates context sensitivity, something Golang tries not to do. But like I said before, you're blaming unclear code on the language rather than the developer. It's an optional feature, so don't use it in inappropriate situations. It's like the whole goto statement argument. Nobody is suggesting we all using goto 's just bec…

> But like I said before, you're blaming unclear code on the language rather than the developer. It's an optional feature, so don't use it in inappropriate situations.

There's a 30 line function claimed to be a refactor of production code in the article we are discussing. It's not my whole cloth example. Heck, my first post was commenting on the structure of that very function hoping it was a defactoring example. People have chosen to focus on the other point in that post.

> So yes, you are not wrong per se. But you are greatly exaggerating the issue.

I understand what you're trying to do but I'm pointing to the overarching article. I didn't make this scenario up.

Also, the personal context I bring here is how many lectures I get from anti-haskell-pro-Go people lecturing me about simplicity, obviousness, etc ad nauseum about why I should adopt their language. So if you're detecting a bit of frustration here at a double standard, I do apologize.

Post reply on HN