4 ms·
This is why almost every panicky API has a non-panicky variant. Non-panicky APIs can be used in a panicky way via unwrap() or expect(). There are very few pani
by Manishearth 10y ago
This is why almost every panicky API has a non-panicky variant.
Non-panicky APIs can be used in a panicky way via unwrap() or expect(). There are very few panicky APIs, reserved for things where 99% of the time you want it to panic and it would be annoying to have to handle errors all the time. Array indexing is one of these cases, where it would be super annoying to handle errors on each indexing operation.
But if you're in a situation where you expect an index to fail, just use `get()` which returns an Option instead.
APIs do not make the decision for you. At most they decide if the panicky API is easier to use than the monadic error one. Which is where the fuzzy notion of "unexpected" and "expected" errors at the API level comes up, it's good enough to be able to determine what the default should be. Callers still have the power to do something else.
- dikaiosune 10y agoI would kill to have a monadic slicing API for Vec<T>, though. It seems like the one significant exception to the "use whichever works better for you" argument. Of course you can bounds check yourself first and return Err if there's a problem, but there's also no get_unchecked() for slices so you'd pay for the checks twice.
- Sean1708 10y ago> but there's also no get_unchecked() for slices so you'd pay for the checks twice. Yeah there is[1], unless I'm being really stupid... [1]: https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked https://doc.rust-lang.org/std/primitive.slice.html#method.ge...
- dikaiosune 10y agoRather, there's no get_unchecked to get a slice from a Vec. Unlike index, get_unchecked can't take a range as input.
- Sean1708 10y agoAh gotcha, sounds like it could be a good first RFC for someone.
- dikaiosune 10y agoI'll add it to my long list of rust projects I wish I had time to do :).
- spion 10y agoBut if you are a mid-level consumer, you don't know whether you can pick the panicky or the non-panicky API. Do you provide 2 APIs again?
- Manishearth 10y agoNo, you provide the non-panicky API, consumers can convert those into panics easily. In Rust, if your API uses monadic error handling (Result or Option), this is easily chained with other errors and propagated up. Additionally, callers can choose to discard errors they feel should not happen by using unwrap/expect to convert them into panics. If your API uses panics, this can't be cleanly turned into non-panicky things without using catch_unwind (you can, but you shouldn't). In the rare case you make the decision to have an ergonomic panicky API, try to provide a slightly less ergonomic non-panicky one.
- spion 10y agoSo ultimately the reason for providing a panicky API has nothing to do with expectedness, its actually all about performance. Otherwise we'd always go for a non-panicky one. Also, in languages with finally and/or defer, catch isn't supposed to be a problem.
- Manishearth 10y agoI never said that. Not performance, ergonomics. `array[5]` and `array.get(5).unwrap()` do the same thing (with a different panic message) and have the same performance when optimized (since it should inline). It would be annoying to have to handle the error every time you index, and would kind of ruin the syntactic sugar of indexing. Thus, indexing panics, and you have `.get()` if you want to not panic and use monadic errors (but as you can see, you can make `.get()` panic too by unwrapping it). The same goes for other panicky APIs, they're panicky because 99% of the time you don't want to deal with that error since it's an "unexpected" one which means something went horribly wrong and there's no sane way to continue. For the 1% of the time you do need to deal with that error, you can use the alternate Result/Option-based API.