Live data from Hacker News

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

github.com

201–210 of 425 posts

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

#201

Earlier quoted context omitted.

Go does not force you to think about errors at every single point. If a function returns only an error (such as, for example, os.Mkdir), the language will happily let you drop the error on the floor.

And that's totally fine. I don't always want to be fighting with monads. If I did I'd write Haskell code. Go is the quick and dirty git-er-done tool that provides quite a bit more performance and type safety than Python, but maintains some of the development speed/ergonomics. Here's the thing, some of us don't want Rust. It looks great! It's perfectly awesome for it's primary domain (i.e. re-implementing critical por…

Wait, what? The OP said that they like Go’s error handling because it forces them to think about errors and make their code more robust. You’re saying you like Go as a “quick and dirty git-er-done tool”. Those are opposite viewpoints! For your use case, it seems like something like try() being added to Go would be a benefit, since it would make it easier to write “quick and dirty” code that still provides at least basic error handling.

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

#202
post #150
post #61

Earlier quoted context omitted.

>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…

> 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…

The nice thing about a statically typed language having standard golint and gofmt is that code is generally self documenting. So I wouldn't ever type that function call without seeing the function definition (in my editor or wherever else I found the API reference).

But I agree, the fact that Go allows this is bad, imo. It would be better if you had to explicitly suppress errors, even with something like this "_ = doThing()" just to make it harder to miss.

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

#203
Personally, I feel that the motivation for the issue is one of convenience. The most common use case is changing the flow control in the event of an error to return from the current stack. I'm not a fan of defining an error handler. This seems far too intrusive and cumbersome and a bridge too far.

GoLand gets around this somewhat by adding in the Live Template of "err" being a macro expansion for the if err != nil { return }. However, it still adds those 3 lines below each requisite call.

If they added a new keyword that took the place of this macro, would that be too intrusive? Clearly, this only works if you have named return values.

It would be nice if there was a bash/Ruby-like chaining, such as:

  var1, var2, var3, err := call1(args) &&
  var4, var5, var6, err := call2(args) &&
  ... and more calls and so on ...
  return callN(args)
Where "&&" would perform the if err != nil { return } in-line. Should the first call return a non-nil error as the last argument, flow would be returned to the caller. If not, the flow continues as normal.

This could even be extended in the case of function chaining:

  return call3( call2( call1(args) && ) && )
The downside of using && is that it's overloading the && and may cause some compiler/developer confusion. This was just an example based on a familiar use case (bash); another token can be used.

Rasky suggested something like this based on another proposal in the thread, but using "?" instead.

Another way to approach this might be an overlay language analogous to Kotlin. There could be a Go dialect that compiled into Go that provided this feature. Or, possibly an optional "plugin" for go's compiler that added an intermediate transformation step prior to compilation based on new keywords, but this will frustrate debugging and lead to other surprises. Generators tried to do this, but it doesn't seem to have taken off, from the repos I've read.

Just my 2c

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

#204
post #155

Earlier quoted context omitted.

You can pass functions to functions ( https://play.golang.org/p/XNMtrDUDS0 ). So you can do (sans syntax): ErrorCheckerFunc(fn myParams -> MyFunc(myParams), "message") ErrorCheckerFunc(fn myParams2 -> MyFunc2(myParams2), "message2") etc... and then the actual function: ErrorCheckerFunc(fn myFunc, message){ returnVal, returnError = myFunc(); switchError: case error is foo: print error case error is bar: log error prin…

I'm not clear on what exactly you're trying to represent here, but it looks like something that wouldn't work with Go's type system. ErrorCheckerFunc would need to always have the same return type and accept a function with the same type signature.

If only there was a way to make a single function work with multiple different types. A way to "genericize" it, you might say.

Alas, that's obviously completely impossible. Such a thing is beyond the capabilities of us mortal programmers. But maybe one day PL researchers will discover a way. One day...

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

#205
post #179

Earlier quoted context omitted.

I'm not a Rust expert but afaik Rust doesn't enforce error checking since you explicitly need to unwrap(). It's very possible to panic because you forgot to check something. It's similar in Go since you can't compile with unused variable so you need to explicitly discard the error with _. Ex: result, _ := func() This is for multi-value returns, for single value you can even omit the _ https://golang.org/doc/effective…

Having unwrap() in your Rust code is like littering your code base with panic(). It’s not appropriate to use in most production code, but is convenient in prototypes, examples and tests. Your example re Go errors is incorrect. The go compiler allows you to ignore errors in returns without any compiler error. For example err := doThingThatErrs() and doThingThatErrs() are both valid Go code.

My example is correct I explained all of that, multi values -> need to omit, single value can ignore everything.

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

#206
post #47

Earlier quoted context omitted.

I repeatedly tell people that Go takes twice as long to write and half as long to debug. Unless you write perfect code on the first try, the trade off is probably worth it.

That feels about right, but missing the most important measure, IMO, which is it takes 10-100x less time to read and understand a new codebase.

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 question, I have no idea.

These are completely idiomatic examples taken from the Go wiki. They are not readable.

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

#207

Earlier quoted context omitted.

Packages extensively using reflect + interfaces together can be a bit of a pain to work through. :/

Absolutely. But those are clear code smells. Any org with competent code review would flag them and kill them before they proliferated.

Would you consider k8s to be developed by a competent org? They have 2324 func declarations that take or return an interface{} on master right now.

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

#208

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.

Go's the perfect language for sharecropping developers.

I don't get why you're being downvoted. Even Rob Pike is frank is said it publicly but in a more diplomatic way.

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

#209
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?

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

#210

Just try writing three Go programs with error handling, then, try other languages! I was pissed at first. However, now I cannot code in any language without overusing try and being scared of each line. Using Go's error handling is actually making your code smarter, I mean, you don't want your code to break with a weird message because of something stupid. The simplest example is adding a default-path whenever I'm rea…

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)
    }
Post reply on HN