As I've mentioned before, the ? operator shouldn't be called a "try operator". It's more related to throwing/unwrapping. We could have a separate RFC to bikeshed that
I agree, since the word "try" there is inconsistent with the prefix try_ used all over the library. (As ? is about early-returning while try_ is about producing a success/failure disjunction like Result.)
“Try to open the file or return the error mapped into MyErr::Io.”
“Try to get the value or return nothing.”
“Try to do the parse or return the result unless it’s complete.”
If catch blocks would come, I’d replace “return” with “propagate” given the right context.
To me, ? is a shorthand for a common concept, not a new concept in itself. So that the above sentences also work for the long-form of the pattern is a plus to me. If I want to refer explicitly to ? I’ll mention the question mark (operator).
Why not just call the ? operator question?
As such, appending ? to an expression could be called questioning an expression.
For example, turning fallible_fn() into fallible_fn()? would be to question the function call.
It’s precise and succinct, and it’s a verb that’s not yet associated with any related error-handling concepts.
@hyeonu I don’t think unwrap is appropriate here as unwrapping implies a panic on the non-happy path.
Returning to this, I think this might be the best fit. I have generally opposed
fn try_fn() -> T throw[s] E
in part due to concern about obscuring the external return type and in part because calling a function cannot "throw" on its own; only a ? expression can. However, with the async proposal using the interior return type of the function in the function signature, and the possibility for yield, i.e.
async fn foo(arg: Arg) -> Return yield Yield
it seems like it's better for the language to do this consistently for this type of feature. In each case, Rust is exposing a value reifying the annotated effect at the function boundary, but leaves this type unmentioned in the function signature. And in each case (well, I'm not sure about generators, but certainly for futures and results), there's an associated caller-side syntax which explicitly propagates the effect. If the annotation marking this effect in a function signature is throw[s], then logically, propagating that effect is 'rethrowing'.
Of course, a consistency argument only gets you so far. Certainly the trade-offs are different in each case, with the arguments for how async handles the internal/external return type dichotomy being particular to that case. I don't think the pedagogic value of being able to say that the noted return type is always the internal return type can be dismissed, however.
I like maybe operator the best because it describes what it is doing and these sorts of exceptions are not really thrown in rust they are returned in a Result. Since we are not talking about panics right now
My brain has been saying this internally for all this time; but I thought I was the only one. I think it's quite a nice name since we are conditionally rethrowing faults / failures. The conditionality is I think obvious so it can be omitted.
Other languages already use ? for option-chaining. While Rust's ? can do that, it's really designed around error propagation. Maybe represents optional values in some other languages (such as Haskell). It would be a bit unfortunate to use option-related language for a feature that might already be mistaken for option-chaining. Of course, it wouldn't be the end of the world.