5 ms·
So, I see tons of unwrap() in Rust code I've looked at in the wild. I understand the concept of unwrap() and Option types. What would this type of code look l
by jcurbo 10y ago
So, I see tons of unwrap() in Rust code I've looked at in the wild. I understand the concept of unwrap() and Option types. What would this type of code look like with proper error handling? It seems like it'd devolve into a ton of if-then statements like in C.
- akiselev 10y agoFirst, you'd use match statements instead of if-then so the worst case scenario already looks much better than in C, especially since Rust has enum decomposition and makes expressions first class (you can do let y = if (...) { y } else { z }). There are a lot of ways of combining control flow and assignment operators to decompose union types like Option and Result (which is Option with error E instead of None). For example, you can do if let, while let, or let x = match(y) { ... } that allow you to handle errors without jumping through hoops like you would with C returns or C++ exceptions. For a library consumer this covers a large number of cases. Second, most of the time you can use the ? operator to greatly simplify error handling. Any code path that shares the same error type can just pass through errors as if they were an exception. The ? operator is also aware of Into/From trait implementations so in many (or even majority of) cases you can use the ? operator even if the function you're calling has a different error type! If I remember correctly, you can even exploit the module system to provide a per-file Into/From implementation for your custom error type if it doesn't map cleanly across use cases (they just have to be in the same module as the type). Rust's zero cost abstractions and trait system make it really easy to reduce boilerplate without compromising on readibility or discoverability. Third, the Result type has a number of functional operators for responding to and combining results. You can do Result.and_then(...) with a closure or function call to do something when there is no error and Result.or_else(...) to do something when there is an error. You can use the and or or operators to combine multiple results and there are many other utility functions that are universal to Rust error handling that make the entire experience very pleasant, composable, and readable with a little experience.
- sidlls 10y agoIt does turn into if-then statements (some implicit, e.g. via try! or ?), if done properly. But I don't understand the objection or calling it "devolving". Errors have to be handled. This way is as efficient as any other. And, in my view, is cleaner than exception handling systems.
- barrkel 10y agoErrors have to be handled This is a highly contentious assertion, and I don't think it's true for most programs, at least not in the way you're suggesting. Most of the point of exceptions is that errors don't have to be handled; or rather, in most application software, almost all errors should be handled high up in the stack, near the event loop or server request / response dispatcher.
- staticassertion 10y agoThis is the same in rust. Panics end at thread boundaries. So you'd have some event loop with threads / coroutines doing stuff and if they panic you handle it at the top level.
- int_19h 10y agoThere are errors, and there are errors. The kind of error that you'd handle high up the stack is, say, a general I/O error reading a file. But when you look up an item in a collection (or a node in a DOM tree), and it is not found, the only place where you can sensibly handle that is right where the lookup happens, usually. In a language that doesn't follow this philosophy, what you get instead are random NullPointerExceptions etc. If you go and look at a random C# or Java project on GitHub and check its tracker, you will see that - surprise, surprise! - that is exactly the type of error that shows up most.