a_method().context("Failed to complete the work")?;
a_method().context(FailedToCompleteTheWork)?;
[0]: https://docs.rs/anyhow/latest/anyhow/trait.Context.htmlyou want to be able to read code and see a single control flow
? subverts that core requirement
Therefore, you can always see see the control flow of a function.
Moreover, you can go even further if you really really really want a single control flow. You can write a clippy lint to disallow early returns (ban "return" keyword) and question marks. That said, I really don't think this is a good idea. The "return" keyword exists for a good reason.
; doesn't do this, afaict
when you're writing imperative code it's important that control flow (return) is explicitly visible
> ; doesn't do this, afaict
It's chaining together transitions in the state machine that is your program.
> when you're writing imperative code it's important that control flow (return) is explicitly visible
Control flow is visible with `?` or other do-notation variants. If I want to error out in a `Result` context, I explicitly return `Err(bad stuff)`. And if I don't, I explicitly return `Ok(return value)` instead. If I want to introduce a new asynchronous value in js, I explicitly call `new Promise`. And so on.
What's not visible in a do-block is the implementation of control flow. Which is fine, because this isn't the code that controls it - `Ok(Err(x))` is reduced in exactly the same way no matter what `x` is or where it came from. Traditional imperative code is the same way: the runtime system always works the same way, no matter which statements you ask it to execute.
If you do choose to expose the underlying mechanisms of your control flow everywhere, you get continuation-passing style, which is useful in small doses but more or less impossible to reason about at scale.
first()?.second()?.third()?
good: a = first()
if a failed, handle that error
b = second(a)
if b failed, handle that error
c = third(b)
if c failed, handle that error
yield cideally, control flow goes 'down' via func calls, and 'up' via return statements
this is the "trivial to see pattern" -- the code as written
exceptions subvert those simple rules, they say any expression can potentially be a return statement, and recursively so!