Bikeshed: A consise verb for the `?` operator


#1

@kornel said in the Reserve try RFC

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 :slight_smile:

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.)

It was introduced in RFC 243 as the following

An ? operator for explicitly propagating “exceptions”.

So I guess the official name is the “explicit exception propagation operator”, but that’s a bit of a mouthful and a poor trait name.

But I can’t come up with something that makes me happy. What would you call it?

My mediocre efforts so far:

  • check: kinda generic, feels boolean
  • test: too overloaded with #[test]
  • propagate: I always misspell this
  • branch: since it’s sortof “jump-if-error”, but confusing with ASM and things like continue
  • separate/sift: for taking out the bit you want – the latter is at least short
  • ripcord: a colourful one from someone on IRC

* braces for the flood *


#2

Some color swatches that might look alright on a bike shed:

  • interrogate
  • inquire
  • ask
  • query
  • sickle (since the ? looks kind of like one of you squint)
  • harvest (related to the above)
  • annie (as in, “are you ok?”)

#3

“rethrow”?


#4

I think unwrap fits well as it’s just unwrap but safer


#5

I always say “throw” when I talk about it, except when I want to be very clear, in which case I saw “throw with a question mark.”


#6

Not a verb, but I always say “maybe”, which seems to match what many other languages call Result (e.g. Haskell). For example,

let x = file.read()?; // I read this as "read the file maybe"

#7

I guess that means I view ? more as an adverb than a verb…


#8

I still always use try.

  • “Try to open the file or return the error.”
  • “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).


#9

So,

me()? // "call me maybe"?

:smile:


#10
  • yolo
  • guess
  • chance

When calling a fallible function, try_foo(), you may take a chance.


#11
  • fork (like branch, but overloaded with forking a process)
  • question (it is a question mark after all)
  • qop (Question OPerator/OPeration)

#12
  • eepo (short for “Explicit Exception Propagation Operator”)
  • try
  • early return
  • bail, synonym for an early return
  • maybe, because I’ve got a result… maybe

#13

I tend to call it either “try” or “question”.


#14

If the do catch block is named trap, then ? could be spring.


#15

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.


#16

A few more:

  • demand (try demanding value)
  • snoop (catch code snooping)

#17

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.


#18

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


#19

:+1:

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.


#20

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.