4 ms·
It's not what errno does in C. errno in C is a thread-local variable which means accessing it is inefficient (it uses thread-local storage, which is much more
by memefrog 3y ago
It's not what errno does in C. errno in C is a thread-local variable which means accessing it is inefficient (it uses thread-local storage, which is much more expensive than a local variable) and you have to do awful things like save errno at the beginning of signal handlers if you call a function in the signal handler that can set errno (basically: any library function).
Whether or not it's better to have a sum type (IMO it isn't), what Go has isn't anything like errno. errno is an ugly wart on the POSIX interface, which is otherwise quite nice. For example, Linux system calls directly return negative error codes, which is a much better way of handling errors, and then the libc has to set errno and return -1. Awful.
>- you have to handle it in-place with no convenient shorthand allowing for handling it at another layer (and usually that’s the only meaningful way forward). Also, error handling is a cross-cutting concern, squeezing it inside your business logic is (in my opinion) a bad thing.
That you say this and then advocate for optional<T>/result<t,e> is insane. That's exactly what a sum type does: it squeezes error handling into your business logic. And no, papering over that with ugly ? operators everywhere is not a solution, it is syntactic sugar. Error handling is part of the logic of your program. It is not just some 'ah we'll return it' thing. Many operations can fail and many errors are recoverable.
- kaba0 3y ago> errno in C is a thread-local variable which means accessing it is inefficient Which is an implementation detail, has nothing to with its semantics what we discuss here. Certain C compilers do wild things with errno as well. I’m not advocating for optional/result types, I personally believe that checked exceptions are the ideal solution, but it is a thoroughly underutilized tool in PL designs (Java has it, though it has many warts, but that is not inherent to the concept). Hopefully with the wake of effect-typed languages it could change. With that said, in Rust’s low-level case it makes sense to avoid exceptions, and sum types are an okay solution, especially if it has a handful macro for bubbling up. What go has is just straight up wrong.
- ssokolow 3y agoJava's ecosystem is moving away from checked exceptions because their "bolted onto the return type as a sidecar" design doesn't compose well with functional-style APIs. Monadic error handling (Rust's Option<T>/Result<T, E>) avoids that issue by putting the error inside the return type as a normal value. (Which is why, on multiple occasions, I've seen people call Result<T, E> "checked exceptions done right/properly".)
- kaba0 3y ago> checked exceptions done right/properly But they fail at including a stacktrace, autobubbling up, auto-unwrap and customizable "hit radius" with a try-catch block (okay, I'm sure some Monadic construct allows for that, but e.g. Rust's version does not).
- steveklabnik 3y agoTry blocks exist in Rust nightly, but given that an IIFE closure gives nearly the same results, there hasn't been a ton of pressure to stabilize them. I wish the team would though.
- ssokolow 3y ago1. Remember that Rust takes a Minimum Viable Product approach to 1.0 releases. There are experiments in adding stack traces in third-party error-handling crates that could eventually lead to additions to the standard library, but we've already gone through at least three iterations (error-chain, failure, anyhow, and possibly eyre) and already have two deprecated methods forever stuck on the standard library Error trait, so they're taking it slowly. (Plus, true exception handling is messy for a language that cares so much about FFI. Look at the discussions surrounding how panic! unwinding should behave at FFI boundaries.) 2. I think completely automatic bubbling would be a misfeature, and the `?` operator is a good balance between concise ease-of-use and the Rust focus on "code is read far more often than it's written". 3. Again, the `?` operator. I think completely automatic unwrap would also be a massive footgun and comprehension hazard. 4. As mentioned in the other reply, try blocks are in development. (See my previous comment about Rust adopting a Minimum Viable Product approach to v1.0) https://caniuse.rs/ https://caniuse.rs/ is a great illustration of how far we've already come and how minimal Rust 1.0 was.