A final proposal for await syntax

I'm going to get a bit meta, and call attention to Stroustrup's Rule:

  • For new features, people insist on LOUD explicit syntax.
  • For established features, people want terse notation.

As written, I see two ways to apply it here.

First, some proposed alternatives, like .await!(), are considerably louder than .await. Not that much longer in terms of number of characters, but a lot noisier looking due to the symbols, including an exclamation mark (a symbol that denotes literal loudness!) whose only purpose is to alert you that "something weird is going on". And certainly more explicit. Applying the rule suggests that experienced Rust users will come to accept and prefer the terser .await once the feature is "established" and they get used to it.

On the other hand, second, there are even terser options available, such as a postfix sigil or nothing at all (making await implicit). Now, terser is not always better, and Rust's philosophy includes making some things explicit that other languages would leave implicit, but it's still worth noting that .await may seem noisier in the future than it does today.

However, I'd also like to suggest a generalization of Stroustrup's Rule:

  • People have a negative reaction to the unfamiliar, especially if it seems to intrude on something they already know.

In other words, if I feel proficient in Rust's syntax, and suddenly there's this new thing that threatens to make my knowledge incomplete and outdated, it feels like:

And I'll want to build a big protective barrier around it in the form of loud explicit syntax, so at least I'll know when I can't rely on my existing proficiency. On the other hand, once I become proficient in the new thing as well, it doesn't seem like as big a deal, and it feels okay to have it "within the perimeter" of potentially conflatable syntax.

Even though .await is not actually hard to learn, per se, it still takes getting used to. As an experienced Rust user, I already have a mental model of the language, where everything feels logical and in its place. To create that model I had to spend time and effort learning new concepts one by one, but now that I've done so it all seems natural. Indeed, if I look back on the language, it feels sort of unnaturally "easy to learn", because what's easier to learn than something you already know? But if you then take that framework and stick a new concept in the middle, the concept comes off as illogical, weird, even hard to learn, simply by contrast.

But I'm not bringing this up just to psychoanalyze people with different opinions to mine... I'd also like to psychoanalyze people that agree with me. :wink: Something that's easier to derive from the generalization is that "people" includes people who are learning Rust. Since most parts of Rust's syntax are similar to other languages that they may already know, they would like to apply their existing proficiency to Rust, and seeing something unfamiliar like .await is a turn-off – in a way that's hard to fully empathize with if you are familiar with it. Something like .await may stand out less if it's just one of many unfamiliar things about Rust, as it would be for a learner, than if it's the only thing you're unfamiliar with... but small unfamiliarities add up. (And languages like Go have been incredibly successful by minimizing unfamiliarities.)

This is just a reformulation of the concept of the "strangeness budget", and it's nothing that hasn't already been considered and articulated multiple times. But I think it's useful to express it in terms of a two-sided cognitive bias:

  • On one hand, unfamiliarity can make something feel more problematic than it really is.
  • On the other, familiarity can make something feel less problematic than it really is (if your goal is making something friendly to newcomers).

Personally, I think .await is a good compromise when considering both of these principles. In particular, if you're a Rust expert, adding a new sigil may seem less weird than using .await, because both are equally new, but only .await intrudes on an existing point of knowledge (field access). But if you're new to Rust... I guarantee a sigil would at least be harder to learn, especially if you unexpectedly encounter it when reading code. Even if .await looks weird, it's pretty easy to guess what it does if you know await from other languages; sigils, on the other hand, are impossible to Google, and even once you learn what they do, they're harder to remember. For the same reason, I strongly suspect a sigil would also make the language feel more arcane overall, even if it avoids the "huh this isn't a field access" shock. (See also: Rust removing @ and ~ sigils in the pre-1.0 period.) The real advantage of a sigil, IMO, is just that it's terser; that's what we're giving up, and I'm okay with that.

But I also think it's important to keep in mind the volume of the opposition to .await: not only does it represent a faction of users in its own right, it serves as the best proxy, however imperfect, for the critical yet silent constituency of new users. And while it seems unlikely at this point that the team will change its decision, I think that opposition should continue to make itself heard.

16 Likes