Live data from Hacker News

Declined Proposal: A built-in Go error check function, “try”

github.com

261–270 of 425 posts

Re: Declined Proposal: A built-in Go error check function, “try”

#261
post #33

This hits at something fundamental about Go, which is what I like the most about it... It's a language intended to have few primitives with an emphasis on code being transparent and errors being values, requiring you to think about what they might be at each point as you're forced to carry them up the chain. Do I particularly like managing errors that way? No, but I do think that it improves the transparency and qual…

> It's a language intended to have few primitives with an emphasis on code being transparent and errors being values, requiring you to think about what they might be at each point as you're forced to carry them up the chain.

Along these lines, I would have much preferred to see the opposite of this proposal: the total removal of named returns. They add magic and confusion, and they are redundant with normal returns. Except in the absolute simplest and shortest functions, I always reject named returns during code review. They are currently the only example of C++ style policy declaring we-don’t-use-that-feature-in-our-org I’ve run into with Go. Try/check would’ve been the second.

Re: Declined Proposal: A built-in Go error check function, “try”

#262

Earlier quoted context omitted.

Try makes it worse because it is so easy to miss when reading the code. Because it encourages nesting function calls, which is harder for a human to parse than separate statements across lines. Because it means you can exit the current function from the middle of a line of code, and what runs before or doesn't run before is based on order of operations rather than requiring the exit to be a statement on its own line…

> Because it encourages nesting function calls, which is harder for a human to parse than separate statements across lines. I absolutely agree. Beyond the human parsing aspect it also makes commit changes easier to reason about and review. I want functionality to be limited per-line and view the ability to combine a lot of functionality into one line as a liability more than a benefit. Go's error handling isn't caref…

I thought it could lead to doing method chaining for a fluent like API which I find cleaner than how things work now.

Re: Declined Proposal: A built-in Go error check function, “try”

#263

Earlier quoted context omitted.

try errors in elixir: with {:ok, val1} handle_notfound_error() {:error, :eperm} -> report_permission_error() _ -> raise("don't worry this process is supervised, let it crash!") end low cyclomatic complexity makes for a nice user experience, and you learn the philosophy of "if it doesn't work, just turn it off and on again". Why be scared? Just let it go. The VM has your back.

Seems identical to Java: try { var val1 = happy_path1(val0); var val2 = happy_path2(val0, val1); var val3 = happy_path3(some_val); function_might_crash_let_it_crash!(some_val); return happy_result(); } catch (NotFoundError e) { handle_notfound_error(); } catch (PermissionError e) { report_permission_error(); } catch (Exception e) { throw new Exception("don't worry this process is supervised, let it crash!"); }

If you're rethrowing the exception, what happens in the VM if that exception is not caught?

IIRC, the VM exits, so, it's not at all identical. There are potentially severe nonlocal effects and you're already coding defensively by putting a catch/rethrow.

Re: Declined Proposal: A built-in Go error check function, “try”

#264
post #61

Earlier quoted context omitted.

> Do I particularly like managing errors that way? No, but I do think that it improves the transparency and quality of a lot of Go projects. So long as we can all agree that it feels super bad, I guess this is fine. But it does sort of mean that Golang approaches the Java world back with checked exceptions where principle trumped ergonomics. That lead to a world where folks felt "forced" to use Java, and that's a sti…

>So long as we can all agree that it feels super bad, I guess this is fine. Actually, I don't think everyone agrees it feels super bad. I personally like having all of my error handling be explicit, painfully explicit even. >approaches the Java world back with checked exceptions where principle trumped ergonomics. I also have to disagree here. To me, checked exceptions are the worst of both worlds. Here you have addi…

It is not difficult to accidently not check them. Like:

  result, err := doThing()
  if err != nil {
    return nil, err
  }

  result1, err := doSecondThing(result)
  return result1, nil
Will not trigger a compile time error.

Re: Declined Proposal: A built-in Go error check function, “try”

#265
post #150

Earlier quoted context omitted.

> Go doesn't even really force you to check your errors, it just makes it harder to accidentally not check them. Like: I dislike it because it does the opposite, it makes it too easy to accidentally continue execution when there is an error: doThing(); // Error doOtherThing(); Which isn't possible with Exceptions. The only thing that would signal that error handling is missing is the absence of boilerplate to handle…

I don't know go, so I'm confused here. If nothing failed, the error is just made silent? The program will move to doOtherThing, as if nothing failed, and everything will move forward?

The error was just ignored. if doThing() had some side effect that doOtherThing() depended on then you will never know why doOtherThing() isn't working the way you expect it to be.

Re: Declined Proposal: A built-in Go error check function, “try”

#266
post #210

Earlier quoted context omitted.

try errors in elixir: with {:ok, val1} handle_notfound_error() {:error, :eperm} -> report_permission_error() _ -> raise("don't worry this process is supervised, let it crash!") end low cyclomatic complexity makes for a nice user experience, and you learn the philosophy of "if it doesn't work, just turn it off and on again". Why be scared? Just let it go. The VM has your back.

What's the equivalent in elixir for something like this? func do(a Param) (res Result, err error) { var aPrime T if aPrime, err = getResource(a); err != nil && err == RecoverableError { aPrime = definitelyNoErrorAlternativeGetResource(a) } var aPrimePrime T ... // many more steps return doSomething(aPrimePrimePrime) }

Thought I'd show it in Java for comparison's sake:

  Result do(Param a) throws Exception {
    T aPrime;
    try { aPrime = getResource(a); } catch (RecoverableError e) {
      aPrime = definitelyNoErrorAlternativeGetResource(a);
    }
    T aPrimePrime;
    ... // many more steps
    return doSomething(aPrimePrimePrime);
  }

Re: Declined Proposal: A built-in Go error check function, “try”

#267

Earlier quoted context omitted.

Disagree hard! a = append(a[:i], a[i+1:]...) That’s the recommended implementation of erase(). After this, is the original object referred to by ‘a’ modified? How can you tell? Let’s pop from a stack: x, a = a[len(a)-1], a[:len(a)-1] Did you read that 100x faster than ‘a.pop()’? Now this: a = append(a[:i], append(make([]T, j), a[i:]...)...) This is an operation called “expand.” What does it do? It is an honest questi…

Slice operations are deliberately verbose in this way so as not to hide the cost of allocation that goes along with them. They are not common in code, but they do make good strawmen when you want to counter general points with specific ones.

Slice operations are verbose because abstracting over them requires generics. Generic operations which don't allocate, like pop, are just as verbose as generic operations which do, while operations on slices of a specific type can be made non-verbose because it is possible to abstract over those. There is no principle of "deliberate verbosity so as not to hide the cost of allocation".

Re: Declined Proposal: A built-in Go error check function, “try”

#268

This thread is rife with "Go should have Try because I want Try" that also seem to be made by developers that do not write Go. It seems confusing to me that voices generally involved from Go are so demanding of its maintainers. Curious, are there full-time (or at least Primary) Go developers that are upset by the lack of Try?

I am a full time developer in go. I feel the lack of good error handling every time I write a function call and then have to use the same if statement to check its result.

Re: Declined Proposal: A built-in Go error check function, “try”

#269

Earlier quoted context omitted.

> But it results in still less cumbersome code, since you only need scoping for the error handling portions.) There isn't a meaningful difference in cumbersomeness between having two try-catch blocks and two if-err blocks. There is a meaningful difference in cumbersomeness between what Go has today and "try foo(try bar())". Which is why it's so unfortunate that the community killed the try proposal. > But forgetting…

> any code search reveals that "if err != nil { return err }" is everywhere Code searches in languages with exceptions tend to wrap the tryblocks around massive portions of code instead of the individual function calls to the point that you have a top level doing: try: ...program here... except: print('¯\_(ツ)_/¯')

But that is exactly how error handling usually works, especially if cleanup is handled separately - you just need to propagate the errors, usually all the way up to the user, who is the only one who can take a meaningful decision.

Almost all actual error handling in code is either error translation and re-throw, resource cleanup, or automatic retries (sometimes you retry the same request, sometimes you try a fallback option, but it's still the same idea).

The user however may be able to check and actually fix their internet connection, they may fix the typo they did in the config file, they may call support to see what's happening to the database etc. - your program can't do any of these things.

That's why exceptions work so well in most languages, especially GC languages where you have dramatically fewer resources to cleanup: they bubble up automatically towards the initial caller, which is often the user. Threading messes with this, but if you use the more modern async style (async/await in most languages) you get proper exception propagation even then.

Re: Declined Proposal: A built-in Go error check function, “try”

#270

With try, Go might have been a language I'd have enjoyed using. It's a shame. Right now, I see Go as being anti-abstraction and anti-cleverness, and I'd rather not work on codebases in which the language of choice is designed to deter creativity and encourage monotony. Heavy use of Go is a big negative when I evaluate potential projects to work on.

Indeed, I like to think of Go as basically the opposite of Lisp.
Post reply on HN