Live data from Hacker News

Python errors as values: Comparing useful patterns from Rust and Go

inngest.com

71–77 of 77 posts

Re: Python errors as values: Comparing useful patterns from Rust and Go

#71

Earlier quoted context omitted.

Yup, don't allow nonsensical states (User+Exception or None+None) to even exist. The original is more like Go approach which is a big flaw with the language.

Go can be `tuple[User | None, Exception | None]` or `tuple[User, Exception | None]`, depending on whether you're returning a pointer. But yea, Go's approach has its warts. Like if you aren't returning a pointer then you need to return the zero value (e.g. `User{}`) even when returning an error

Yeah but pointer + nil also have issues: https://go.dev/doc/faq#nil_error

I've also seen APIs that allow returning both error and a value ("something went wrong, but here is a fallback or something") which are of course extremely confusing given the usual style.

Re: Python errors as values: Comparing useful patterns from Rust and Go

#72

Earlier quoted context omitted.

Go can be `tuple[User | None, Exception | None]` or `tuple[User, Exception | None]`, depending on whether you're returning a pointer. But yea, Go's approach has its warts. Like if you aren't returning a pointer then you need to return the zero value (e.g. `User{}`) even when returning an error

Yeah but pointer + nil also have issues: https://go.dev/doc/faq#nil_error I've also seen APIs that allow returning both error and a value ("something went wrong, but here is a fallback or something") which are of course extremely confusing given the usual style.

Oh I agree, I've run into too many nil pointer panics. I wish Go had a first-class way of expressing optionality, rather than using pointers

Re: Python errors as values: Comparing useful patterns from Rust and Go

#73

Earlier quoted context omitted.

> Exceptions are just spooky GOTO and a distance I couldn't agree more! When you throw exceptions it's unclear where the control flow will go

I just don't see how multiple levels of if err: return nil, err in the call stack makes things any clearer? Or how having many instances of that snippet scattered everywhere makes the code easier to read?

It makes the happy path harder to read but the unhappy paths much clearer. I hated this aspect of Go when I first started with the language but I love it now

Re: Python errors as values: Comparing useful patterns from Rust and Go

#74
post #43

Earlier quoted context omitted.

This topic is explicitly about considering alternatives to the current Pythonic way.

And GP is pointing out (correctly) that most of the time being idiomatic has more net gain than any putative advantage of the non-idiomatic proposal. Exceptions to this are extremely rare.

[deleted]

Re: Python errors as values: Comparing useful patterns from Rust and Go

#75
post #11

The most important thing about writing code is that you write it idiomatically for the language it is in. With Python, idiomatic code is known as Pythonic. def rename_user(user_id: str, name: str) -> User | Exception: # Consume the function user = get_user(user_id) if isinstance(user, Exception): return user user.name = name return user This is not Pythonic. Don't do it. Like it or not, Python uses exceptions. How do…

> What if the program receives an interrupt signal during the get_user call? You shouldn't catch interrupt signals regardless of whether you're throwing or returning errors. This is why your error classes should extend Exception and not BaseException. The interrupt errors (e.g. KeyboardInterrupt) extend BaseException

When writing multi-threaded code, you might want to catch KeyboardInterrupt to cleanly shutdown worker threads. In any case, my point is that you always need to be aware of exceptions in Python. You can't just return them as values and pretend they don't otherwise exist.

Re: Python errors as values: Comparing useful patterns from Rust and Go

#76
post #2

In FileMonger[0], which uses Tauri, I have implemented a `Result` logic for errors in TS, similar to what's available in Rust. It's clunkier, but still much preferable to the mess of throwing. Much easier to handle errors and debug. [0] https://filemonger.app/

Wanna opensource that part as a library, or at least write a blogpost?

Re: Python errors as values: Comparing useful patterns from Rust and Go

#77
post #76
post #2

In FileMonger[0], which uses Tauri, I have implemented a `Result` logic for errors in TS, similar to what's available in Rust. It's clunkier, but still much preferable to the mess of throwing. Much easier to handle errors and debug. [0] https://filemonger.app/

Wanna opensource that part as a library, or at least write a blogpost?

I have written a rudimentary implementation to avoid external dependencies. If you don't mind, a quick google comes up with a couple:

https://github.com/vultix/ts-results

https://github.com/badrap/result

Post reply on HN