Bikeshed: A consise verb for the `?` operator

I am aware that when framing ? as a monadic/applicative construct, the mechanism implementing then is bind.

What I don't understand is how you agree that, semantically,? operates like a conjunction ("then maybe"), but still prefer a verb. The verbs, in your illustration above, are bar(), baz(), etc.

This is doubly hard to reconcile with your argument that try/? is a "happy path" construct. Conjunctions pair well with the happy path, verbs do not.

Compare:

foo.bar, then maybe baz, then maybe biz, then maybe buz

or

foo.bar, therefore baz, therefore biz, therefore buz

with your preferred nomenclature:

foo.bar rethrow, baz rethrow, biz rethrow, buz.

foo.bar propagate, baz propagate, biz propagate, buz.

foo.bar bubble, baz bubble, biz bubble, buz.

I agree that no single word will capture the full extent of the operation, but the above demonstration shows that a conjunction offers more clarity than a verb. The conjunction captures the conditionality of the construct, a quality unmatched by rethrow, propagate, or bubble.

1 Like

I have trouble reading the example code with conjunctions like therefore on the opposite side of the call site from the operator in question (pun intended).

foo.bar()?

foo, therefore bar

The ? operator is clearly in a suffix position, which implies the above reading is in some ways "backwards". It's like the dollar sign, which has always been something I've hated.

$100

One hundred dollars

Compare with temperatures:

21°C is 69.8°F

Twenty-one degrees Celsius is sixty-nine point eight degrees Fahrenheit

The point I'm trying to make is that dollars and degrees are neither conjunctions nor verbs. They are nouns. Guess what else is a noun? bubble

1 Like

I think bubble does well on conditionality, since in a technical context it makes me think of bubble sort, where elements "bubble up" to the appropriate level, like errors do with ?.

Whoops! That's an error on my part. I only meant to add "therefore" where the ?'s are in the original. I updated my examples. Thank you for pointing that out!

I think of it in similar terms, though instead of a bubble sort it's events bubbling up the DOM. I certainly like it the most of the verbs mentioned, but it made me feel uneasy and I wasn't aware of why until I read the exception paper I linked above. I think of ? as the "connective tissue" between fallible actions, much like a conjunction.

I tend not to mentally pronounce ?, but instead I read the expression it’s attached to with question intonation. So I might mentaly read try_thing(foo)? as “try_thing of foo?”, or mutex.lock()? as “mutex dot lock?” (kinda hard to express over text =P). Curious to hear if other folks do this.

Not that it helps give ? a name; personally, I when I read ? not attached to an expression I just mentally say “q”.

2 Likes

I also think about the DOM when I hear "bubble". In web programming it means that an event travels up the tree. There's nothing conditional about it. It just travels upwards. There's only ever one parent element and it travels until it either reaches the root or the propagation is manually stopped.


Let's focus on counter arguments. I'd like to hear some for "check". Various people said they like it, but the only counter argument that was mentioned so far was:

  • Why does it seem generic?
  • The boolean feeling comes probably form "checkboxes" or QA checks. However, those kind of associations are exactly what we what

For "maybe" there was:

I agree with both statements.

3 Likes

I’d probably call it the question-mark operator because that name corresponds directly to its appearance. It would probably also be the most obvious name to search for when trying to learn Rust.

I do like the word check as the verb for this operator, as in: “verify as to correctness”, and for the general connotation of “interrupting the current motion”.

When reading Rust code the ? can also be read as the interjection “check!”, meaning “all right!”. This highlights the happy path while giving a small pause.

5 Likes

"check" is the best name for the concept I've heard yet, whereas, "question mark operator" is the best name I've heard for naming the operator itself. I nominate:

  • Concept: Check
  • Name of Operator: Question Mark Operator

Sounds good to me.

3 Likes

What about the "gate" operator? The concept of having a gate/door that you can pass or be rejected from seems appropriate. As if ? was a bouncer at the door for the "happy path". Maybe "bouncer" operator could work as well.

EDIT: Also sounds like a purgatory where the distinction between good and bad is made :stuck_out_tongue:

Purge: In history, religion and political science, a purge is a removal of people who are considered undesirable by those in power from a government, another organization, their team owners, or society as a whole.

1 Like

This reminds me of the 2nd definition of limbo:

an uncertain period of awaiting a decision or resolution; an intermediate state or condition.

Though, when I think of a "limbo operator", I think of the competitive kind.

1 Like

Still ‘try operator’.

Perl has a really expressive set of conditional constructs that are used like ? (and which, TBH, I'd really appreciate in rust). They come in two flavours, but in general you use whichever expresses intent and "happy path" best.

  • logical binary operators, and / or, that are the same as the regular ones but bind with lowest precedence, and shortcut like normal (left-to-right)
  • postfix if and unless that evaluate the expression condition on the right first (unless x is obviously just if !x and can be used prefix or postfix)

They're often used with looping early return (next) or exception (die and others) mechanisms, eg:

next unless $prerequisite;

open() or die "bozo!";
my $v = thing() or return; 

do_thing() if $option;

evaluate() and perform();

Rust has a way to go before it gets this naturally expressive around working with Result, but I hope we can get there one day.

So, in the context of the current question, I tend to read ? like and (or "and then") when it's chained foo()?.bar() and like or die at the end of an expression. More specifically, I never read it as unless. For rust, it's probably more like "or (return) error".

As for how to pronounce it, lisp has a convention to name used as boolean predicate checks as foo-p, and they're pronounced with a question-like inflection. I sometimes mentally read it that way, but it probably doesn't work out-loud for all the podcasters out there..

For naming the operator, in the same way that ::<> is named turbofish but not really pronounced out loud like that when it happens, I like the "bubble" or "bubble chain" operator, just for whimsical value.

Now, if we're really going for whimsy, given this thread, we should call it the shed operator. Like a crab unwraps itself by shedding an exoskeleton, and a call chain can shed errors.

2 Likes

I made this suggestion somewhat in jest, but.. it's growing on me.

So, yeah, the shed operator unwraps values and sheds errors, like a shedding crustacean.

Just realised nobody’s put it forward before now, so I’ll just say it: I see it as the expectation marker, or the marker for expected result (in the sense that it operates akin to .expect (without the panic)). When I write it I’d read something like let output = source.read()?; as “source.read() with the expectation that it fills output”.

While it’s not super short, or pithy, really what we’re looking at is some kind of result marker. For shorter verbiage I’d suggest “anticipate”(/“anticipation marker”). Throwing the terms expect and anticipate into a thesaurus leads to some fun names though (“the conjecture marker”).

To contextualise it:

let my_value = obj.get_value()?; // get value with expectation
// code that expects it.

Since it doesn’t panic, or except in a C+±like way, I’d say it’s an expectation over an exception.

I don’t know if this helps, but the new C error handling paper seems to be using _Try for their equivalent of the ? operator:

int some_function(int x) _Fails(float) {
  // Return failure if x is zero
  return (x != 0) ? 5 : _Failure(2.0);
}

char const *some_other_function(int x) _Fails(float) {
  // If calling some_function() fails, return its failure immediately
  // as if by return _Failure(some_function(x).right)
  int v = _Try(some_function(x));

  return (v == 5) ? "Yes" : "No";
}

(from https://docs.google.com/viewer?a=v&pid=forums&srcid=MTEwODAzNzI2MjM1OTc0MjE3MjkBMDIyMjg0NDY2NTc4NzYyMDQzODYBX1RlYjRCNjREQUFKATAuMQFpc29jcHAub3JnAXYy)

2 Likes

And if that gets in the C standard, there will be a stdbool.h like header according to https://groups.google.com/a/isocpp.org/d/msg/std-proposals/HV-7y5XZmBw/dGNKhKUUAgAJ so that the idomatic way is to write fails(float) instead of _Fails(float) and try instead of _Try etc.

So the whole “try, throw and catch refer to an mechanism that automatically travels up the call stack to the nearest catch block” argument might get watered down in the future. Especially in the systems programming space.

Several months ago I wanted try-throw-and-catch-as-keywords to stay as far away from Rust as possible. But now C and C++ might get these ‘static exceptions’, and this idea seems to be well received in the C++ community as far as I can tell. (I listen to CppCast & Cpp.chat and read some trip reports.) Which has caused me to do a 180. I have started to really warm up to @withoutboats’s suggestions of calling it “throw” as well as -> i32 throw(s) i32 being sugar for -> Result<i32, i32>.

3 Likes

Omg I love that!.. I'm so calling it the Annie operator!

1 Like

Expand it to interrogative for interrogative marker and that's growing on me.

Using it a fair bit yesterday I realised it's really an interrogative of the child function. Whereas I kept viewing it as how the programmer/reader would interpret it, the internal relationship feels very subordinate (like an indirect question), but can also be direct (in many cases where the variable isn't returned).

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.