Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The Rust Result type has:

  - map / map_err
  - and_then / or_else
  - unwrap / unwrap_or
And countless of other functions making it very practical to chain computations without having to pattern match anything.

I do the same in Erlang/Elixir.

In Golang, I need to check every function call, and if I want to know where an error come from, I need to wrap it in an errors.New() because no exceptions = no stacktrace



> and if I want to know where an error come from, I need to wrap it in an errors.New() because no exceptions = no stacktrace

Zig manages to provide traces with very little overhead:

https://ziglang.org/documentation/master/#Error-Return-Trace...

I am baffled as to why error handling in Go remains so impoverished.


Stack traces exist in go[1], I'm not sure why you consider exceptions to be the only way of getting a stack representation.

Not to mention that traditional exception handling advice I've been handed down from the gray beards is to always handle exceptions as early as possible, which is exactly what go forces you to do with their approach.

[1] https://pkg.go.dev/runtime/debug#Stack


Chaining computations hides the error control flow path, which negatively impacts readability.


In general, you can replace pattern matching with a function that takes one function for each constructor of the sum type.

However, doing this kind of ... sucks.


It sucks when you have to use it for everything, but it's a useful enough technique that most Haskell datatypes come with functions that provide exactly this conversion to church encoding.

See eg 'maybe' (https://www.stackage.org/haddock/lts-18.18/base-4.14.3.0/Pre... on stackage) or foldr for lists.

'foldr' is interesting, because it encapsulates a recursive pattern matching on lists. For the non-recursive version, see 'uncons' composed with 'maybe'.


It's probably actually better than pattern matching when there are only two, as in those cases. But even at three, it becomes a mess. And more than three? Yuck.


If your language does currying similar to Haskell, and there's a good order to your constructors / arguments, even with three or more there might be some benefits with partial application.


I don't see why that wouldn't be possible to implement now that the generics are here.


Which is exactly why I said:

> I cannot wait for the Result monad.

Generics make this possible, and will be a huge improvement to Go's error handling.

I'm not saying it will solve everything, but it's a huge step nonetheless.


I think you will find that Go's error handling will not change as much as you suggest. The majority of developers are extremely cautious of generics and found the status quo to be the best balance between readability and conciseness.

Convenience is not a goal of the language, generally.


> The majority of developers are extremely cautious of generics and found the status quo to be the best balance between readability and conciseness.

Most people who use Go have specifically chosen to use it though (or at least sought out opportunities, given that it's not something entrenched like Java being used due to inertia), so yes, most of them are fine with how Go is or they wouldn't be using it in the first place. If Go had generics from the start, I'd imagine most users would be fine with that too due to self-selection.


It doesn’t need to be part of the core language. Everyone can make their own monad, or use the one from a library.


I seem to have lost track of how the discussion reached that point, thanks for the clarification.


Depends on how generic you want this.

In Haskell, you can have functions that work generically over option-types, error-able types, lists, functions, tuples, etc.

In Rust, you have to specifically implement functionality for all of these.

But eg your 'map' function in Rust still works for all lists, no matter what item type. In Go before this change, you had to write a different map function for each item type that could be in your list.

In Haskell, the same 'map' function works for lists, functions, error-able types etc.


Huge no to anything that will require .unwrap() noise everywhere in the codebase. I use Erlang, my code does not have ".unwrap().unwrap()"[1] anywhere.

[1] https://github.com/SeaQL/sea-orm/blob/64c54f8ad603df0c1d9da8...


That's actually a problem in Erlang.

In Haskell, 'Maybe (Maybe Int)' is a different type from 'Maybe Int'.

That means that when you use eg a hash table that returns some kind null value like 'Nothing' on lookup when a key is not found, you can still stick exactly that kind of null value as a normal value into the table and everything will turn out fine.


The comparison here is with go.

Unwrap would look like:

    file := os.Open("foo").Unwrap()
I'll take that over the current go state of the art:

    file, err := os.Open("foo")
    if err != nil {
        panic(err)
    }
Just like "panic(err)" is used infrequently, "unwrap" would be used infrequently. They're comparable, and for the cases where unwrap is okay (test code, once-off scripts, etc), I'd definitely prefer it to the panic boilerplate.


I don't understand this example at all. A Rust programmer would essentially never use unwrap on the return from File::open. It would be like checking open(2) with assert() in C.


That Go would never pass code review unless it is part of a tiny CLI tool or script.


I use rust and my code does not have .unwrap() (and definitely not .unwrap().unwrap()) in it either. That's what the ? operator is for.


The '?' is not a conceptual advance over .unwrap(), it's "just" a major syntactic convenience.


Of course it is. Unwrap panics on error, while ? bubbles up the error instead. But ? wasn’t introduced to replace unwrap, unwrap was always frowned upon. It instead replaces match and return.


It was always frowned upon, but still ended up everywhere (including lots of documentation and example code) because it was less verbose than the match handling. The ? helped remove that last obstacle.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

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

Search: