Live data from Hacker News

Go 1.13: xerrors

crawshaw.io

131–140 of 150 posts

Re: Go 1.13: xerrors

#131

Earlier quoted context omitted.

> Go's error handling is essentially the same as Error/Either/StatusOr (returning errors as values). Not really, it's very annoying to chain calls which can error. Also, as another commenter mentioned, functions which can potentially fail should return sum types and not product types. Compare: do first and first, err := computeFirst() if err != nil { return nil, err } second, err := computeSecond() if err != nil { re…

Apologies, I know very little Haskell - does that example mean that `computeSecond` will always be called, even if `computeFirst` failed? If it does, it's not the same as the Go code which will not call `computeSecond` in that case (which might be a requirement - who knows?) I'm also assuming that `f first second` will return (an error monad?) if either of `first` or `second` are (an error monad?) - is that right?

This version of f can't fail, so "return" wraps its value in the same monad. Normally the "do" block would end by getting a monad from f, just as the Go version would normally let f return an error.

Re: Go 1.13: xerrors

#132
post #12

It seems like golang designers are totally isolated from what's been happening in the last 30 years in languages design. They still insist on their weird way of error handling just like they were stubborn for years and years on the lack of package management and eventually a very weird and rudimentary way of it. It's sad because I use this language extensively but its weirdly mediocre design is totally unfathomable.…

I've been using Go heavily over the last five years, starting with 1.2. Whatever warts the language has in its design, the error handling being one, it's still an excellent language for getting work done quickly, and correctly. I'm far more productive in it than Java, C++, or Python, and I'm old enough to have done lots of Pascal, Lisp, and more scripting dialects than I can count. Having been writing software over t…

I keep checking in on Go, trying to decide if I want to add it to my toolkit, but this argument usually bugs me.

Lisp is simple. Go is half-simple, but in its take on simplicity, it also takes away some constructs that make useful, high-leverage expressiveness impossible.

Some of its other benefits are appealing to me, but that's not one of them. It seems simple on its face only.

Re: Go 1.13: xerrors

#133
post #65

Earlier quoted context omitted.

Rust's type system + the failure crate ( https://crates.io/crates/failure ) is the nicest I've seen. It's similar to Haskell in that errors are part of the return value of a function, and the type system enforces handling of this. _But_ Rust also includes some really nice syntax for passing errors through so I can write this: use failure::Error; fn foo() -> Result { may_return_an_error()?; might_return_a_different_er…

This sounds exactly like Java's checked exceptions.

The two are closely related concepts. You can model checked exceptions as a secondary return type, except without the same first-order representation (e.g. inability to specify checked exceptions in generic terms).

Re: Go 1.13: xerrors

#134
post #129

Earlier quoted context omitted.

> Once Java gets fibers, its concurrency offerings will be a strict superset of golang's. golang doesn't even offer event based async concurrency. Kotlin does that today and I like Kotlin, however the fact is that the class-everywhere Java approach just doesn't sync with me. Go's and Rust approach to OO with value-based types (structs) suits me much better. > golang doesn't even have concurrent data structures Not st…

> Kotlin does that today and I like Kotlin, Kotlin's coroutines are still not like fibers (it's still affected by: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-... ) Java is getting record types as well. That being said, one is free to use whatever JVM language they like and still get the huge benefits of the JVM, regardless of the language. > Not strictly true. It does have sync.Map There's also 3rd p…

> Not to mention casting to and from interface{} which is error prone and very tedious and verbose.

Agreed, but Java's generics are not the best either. When I am looking for an advanced type system in this space I look at Rust, not Java.

Re: Go 1.13: xerrors

#135
post #23
post #12

It seems like golang designers are totally isolated from what's been happening in the last 30 years in languages design. They still insist on their weird way of error handling just like they were stubborn for years and years on the lack of package management and eventually a very weird and rudimentary way of it. It's sad because I use this language extensively but its weirdly mediocre design is totally unfathomable.…

And I am so happy that they won't do anything but the right thing. Over the decades as a programmer I have seen a lot of language come and go. A lot of languages suffer from "features". Where either a language is designed with advanced concepts getting either directly in the way of writing simple programs, or even worse, getting bolted on later on, creating something very different from the initial language. I love t…

>I love the dependable simplicity of Go.

If you like Go, you'll love the simplicity of Brainf-ck, a clean design which is easy to learn, simple syntax, and supported in almost all computing platforms.

Re: Go 1.13: xerrors

#136

Earlier quoted context omitted.

> Go's error handling is essentially the same as Error/Either/StatusOr (returning errors as values). Not really, it's very annoying to chain calls which can error. Also, as another commenter mentioned, functions which can potentially fail should return sum types and not product types. Compare: do first and first, err := computeFirst() if err != nil { return nil, err } second, err := computeSecond() if err != nil { re…

Apologies, I know very little Haskell - does that example mean that `computeSecond` will always be called, even if `computeFirst` failed? If it does, it's not the same as the Go code which will not call `computeSecond` in that case (which might be a requirement - who knows?) I'm also assuming that `f first second` will return (an error monad?) if either of `first` or `second` are (an error monad?) - is that right?

In the error monad above, computeSecond will not be called if computeFirst failed. But in other monads (which have the same syntax) computeSecond MAY be called depending on the rules of composition.

return is a bit of a misnomer in Haskell -- it really means "wrap this value in the monad supplied by the context." So as other commenters have mentioned, f(...) cannot fail. Non-monadic Haskell functions never use return.

If f could fail and you indeed wanted to propagate its error if it did fail, you could write the code as

    do first 

Re: Go 1.13: xerrors

#137
post #23

Earlier quoted context omitted.

And I am so happy that they won't do anything but the right thing. Over the decades as a programmer I have seen a lot of language come and go. A lot of languages suffer from "features". Where either a language is designed with advanced concepts getting either directly in the way of writing simple programs, or even worse, getting bolted on later on, creating something very different from the initial language. I love t…

>I love the dependable simplicity of Go. If you like Go, you'll love the simplicity of Brainf-ck, a clean design which is easy to learn, simple syntax, and supported in almost all computing platforms.

Sorry, I don't see how your comment contributes to the discussion. You have heard of C? A language which most of the Unix infrastructure is built upon? It turns out, Go is a language, which keeps a lot of virtues of C, adding just enough to it to fix some of the shortcomings of C, adding more safety and convenience.

Re: Go 1.13: xerrors

#138
post #110

Earlier quoted context omitted.

> Java, C++ and Python have exceptions to keep you from littering your code with error handling, and code with exceptions is hard to read. The line of code you are looking at any point in time may instantly jump to another place, effectively, Rust and Swift both manage to make error handling easy while keeping this nice "errors are just values" property. Go could easily have added Rust-like or Swift-like error handli…

How is rust error handling better than gos?

Okay, I'll bite.

It's better in many ways.

Firstly, rust has sum types, so it's possible to have exhaustive matches and know you've handled every case. This isn't possible in go. For comparison:

    // go
    val, err := doSomething()
    switch err.(type) {
    case *SomeErrorType:
      // handle
    default:
      panic("inexhaustive error check (at runtime, only if that error type is hit)")
    }
    
    // rust
    let (val, err) = do_something()
    match err {
      Err::SomeErrType(inner) => { /* handle */ },
    }
    // won't compile if the match isn't exhaustive
Note as well that you have to return the error interface, not some more specific type, in go because of the "nil struct is not a nil interface" gotcha. Juggling around structs that are returned as errors is basically impossible to do safely, so everyone returns the error interface. This is another way the language causes error handling to be worse.

Next, generics in rust allow for nicer chaining of computation in the presence of errors. Let me show you two examples. Again, the go and rust code is as identical as I can make it:

    // go
    val1, err := computation1()
    if err != nil {
      return nil, err
    }
    val2, err := computation2(val1)
    if err != nil {
      return nil, err
    }
    return computation3(val2)

    // equivalent rust
    computation1().and_then(computation2).and_then(computation3)
    
    // also equivalent rust
    let val1 = computation1()?;
    let val2 = computation2(val1)?;
    computation3(val2)
The ability to have a generic 'Result' type to chain computation allows for code to be more readable, while still having all the benefits of errors being values.

The ability to have a generic 'Option' instead of 'nil' also is very helpful, but enough has already been written about null pointers that I don't wish to rehash it here.

Finally, in practice, rust's higher level features (namely macros) allows libraries to create very powerful developer abstractions around errors, like those offered in the 'failures' crate, all without having any runtime overhead.

In practice, all of these things also combine to result in libraries offering better error types and allowing callers to handle errors well.

Re: Go 1.13: xerrors

#139
Not sure why people are bashing Go because of it's choices.

Looking forward to shit storm once they introduce generics in near future. I am sure people will still complain that this is not how parametric polymorphism should be implemented.

Re: Go 1.13: xerrors

#140

Earlier quoted context omitted.

I've been using Go heavily over the last five years, starting with 1.2. Whatever warts the language has in its design, the error handling being one, it's still an excellent language for getting work done quickly, and correctly. I'm far more productive in it than Java, C++, or Python, and I'm old enough to have done lots of Pascal, Lisp, and more scripting dialects than I can count. Having been writing software over t…

I keep checking in on Go, trying to decide if I want to add it to my toolkit, but this argument usually bugs me. Lisp is simple. Go is half-simple, but in its take on simplicity, it also takes away some constructs that make useful, high-leverage expressiveness impossible. Some of its other benefits are appealing to me, but that's not one of them. It seems simple on its face only.

[deleted]
Post reply on HN