Hacker News new | ask | show | jobs
by tialaramex 1314 days ago
I feel like this document makes the Try operator (?) and its associated trait more mysterious than necessary. Most people probably won't need to implement Try, especially before it is stabilised, but it's not that much more complicated than say, AddAssign the trait which you implement to make the Add Assignment (+=) operator work on your type.

The key trick of Try is that it converts something (by default an Option or a Result or async Polls of those types) into a ControlFlow†. This is the one nice trick about Exceptions in languages which have them - they influence control flow, but Rust reified it as a vocabulary type which I think is much better. We can pass this thing back to somebody who cares about the resulting control flow, not just suddenly wrench the control flow out from under the rest of the software.

† unlike Try, ControlFlow is actually a stable type you can use today in your Rust and, like std::cmp::Ordering it's useful even just as a vocabulary type, disregarding its semantics. Library A and Library B, written by different people, in different circumstances, both agree that ControlFlow::Continue is continue and ControlFlow::Break is break whereas who knows what the boolean false from Library A means to Library B, let alone what if anything Library B's custom type BPartialResult means to Library A's code.

3 comments

BTW if you have read about the `Try` trait before and are wondering what `ControlFlow` is, read it again: https://doc.rust-lang.org/nightly/std/ops/trait.Try.html

`Try` was recently changed significantly with the introduction of `ControlFlow`. IMO it's a big improvement.

TIL what ControlFlow is. This is super interesting and solves some problems I thought were impossible.

Error handling has gone from uber painful in 2018 to pretty decent in the latest editions.

I do some hobby projects in Rust.

One gotcha that I hit was using ? in sample code in documentation. It didn't work, so I had to replace all of my ? with .unwrap().

I generally consider .unwrap() a poor example, because it encourages writing code that could crash a program unnecessarily.

You can use it in sample code in the documentation, but you will need to add a bit of boilerplate around it: https://doc.rust-lang.org/rustdoc/write-documentation/docume...
You can set lints for cargo, for example to warn or even disallow compiling with any `unwraps` or `expect`s. I use cargo-cranky which makes using lints super easy, cargo doesn't yet have native functionality to set which lints should be enabled or disabled.