| It's not like exceptions because it's not used like exceptions. You only use panic if you want to crash the whole program. If you don't want to crash the whole program, you don't use panic. You do not want to crash the whole program if the user data failed to validate, so you do not panic in that case. If a library panics on invalid user data, that's a pretty serious bug. I've been programming in Rust since it came out, and a couple of those years professionally, and I don't think I've ever seen anyone use catch_unwind. Maybe once in a test case? To be concrete, let's talk about an example of a panic. Say you want to access the 3rd element of a vector. There are two cases: 1. You're not sure whether the vector actually has three elements on not. In this case, you call `my_vector.get(2)`, which returns an Option, and you handle the case where it's present and the case where it's not. This is standard error handling. 2. You are sure that the vector has at least three elements. Perhaps you just checked its length for some other reason, or you are careful to maintain this invariant, or you just constructed this vector by pushing 5 elements onto it. In this case, you would typically use `my_vector[2]`, which panics if the vector is too short. For #2, the thing to notice is that this function literally never panics, under any input whatsoever if it is written correctly. Should that fact really clutter up its type signature, either by forcing it to return a Result type or by forcing it to have a "throws panic" marker? EDIT: This is for a function that uses a possibly-panicking operation, `my_vector[2]`. There are also the functions that define a potentially panicking operation, like the vector indexing function itself. You could put a marker in the type signature of those, that would be reasonable. Though it would only be for users; the compiler wouldn't care. |
I think Rob Pike even said it's easy to see where a program fail in one of his talks?
But to me the superb thing about exceptions, is that error handling can be done where it makes sense. I.e. we can try{ problem-code }catch(problem){ handle problem } in a single location. Otherwise we end up peppering the entire code base with a ton of error checking far down the call stack, where we really cannot do much about the problem anyway (unless we are writing command line tools where error handling is just writing the problem to stderr).
Exceptions gives us a nice way to let problems bubble up to the surface, while also stating what the problem was, and where it occurred. That is great IMO.