Live data from Hacker News

A final proposal for Rust await syntax

boats.gitlab.io

181–190 of 265 posts

Re: A final proposal for Rust await syntax

#181

I wish more language constructs used postfix notation. It looks so natural to me when reading from left to right. Consider: [a+2 for a in as if a > 3] Vs as.filter(a -> a > 3).map(a -> a + 2) Sometimes I even wonder why variable assignment has to precede the assigned expression.

> Sometimes I even wonder why variable assignment has to precede the assigned expression.

I think there's a good discussion to be had on preferring either prefix or postfix operators, but the answer to this question (which is also the answer to the question "why are we so accustomed to prefix keywords?") is easy: because ALGOL did it.

Re: A final proposal for Rust await syntax

#182
post #172

Earlier quoted context omitted.

Curiously, will there be limitations to where it can be used? Eg, imagine a `foos.iter().map(|f| f.await).collect:: >()`? That seems crazy, think it'll be possible?

Not as things are currently designed. This is similar to how you can’t use things like the `?` operator, break, return, etc. inside a lambda and expect it to affect the outer function: it doesn’t work because lambdas are treated as their own functions. Personally I think it would be cool to pursue an extension to lambdas that would allow some of those things to work, but I’m not a Rust team member or anything, just a…

Technically, `?` can work in lambda's if the return value is a `Result` - though it won't work like it's being called as part of a normal loop or whatever. That's largely mitigated by the combinators available on an interator of `Result`s.

So I think we'll just need similar tooling for lambdas - perhaps an `async` modifier for them? That (I think) would lift await stuff up to `?` in terms of lambda support.

Re: A final proposal for Rust await syntax

#183

I figure the reason the proposed syntax looks gross is because other languages have been using a prefixed await for many years. The Rust decision seems well thought out though, enough to make me wonder if perhaps other languages have been doing it wrong. My first experience with futures was in the form of QFuture ( https://doc.qt.io/qt-5/qfuture.html ), and there you call .result() to block and wait for the result. T…

IMO it's awkward for the following reasons: (1) It looks like a field access, and field accesses are "cheap", method invocations aren't. This breaks the 'conceptual weight' model when you look at a line of code. Field accesses are simple and understood. It becomes impossible to gauge the 'cost' of a line by looking at it unless you're intimately familiar with the workings of 'await' and there's no visual cue. (2) If…

> (2) If we create new such postfix operators in the future we'll have to break yet more source code by reserving yet more field names in all structs in all existing code.

This is already the case; all keywords in Rust are reserved keywords, not contextual keywords, so you already can't have a field named, say, `return`, despite the fact that a hypothetical `foo.return` would otherwise be unambiguous. Further, with the Edition system and rustfmt, reserving keywords in this manner shouldn't be disruptive.

> (3) It's a one-off that's different from everything else in the language that's being shoehorned into existing syntax.

The paragraph at the end of the OP suggests that the language team is seeking to propose allowing certain other keywords (specifically those that can return useful values) to be used in postfix position (which implies that `await` could then be used in prefix position as well), which could e.g. (I'm spitballing here) replace the `.for_each()` method on iterators with just `.for`.

Re: A final proposal for Rust await syntax

#184

The syntax feels a bit Ruby-ish, doesn't it? Here's an example from the article of how they could expand the syntax in the future: foo.bar(..).baz(..).match { Variant1 => { ... } Variant2(quux) => { ... } } Compared to some Ruby: 5.times { puts "Hello world!" } Note I'm by no means an expert in Ruby or Rust, this is just what I thought of when I saw the syntax.

Re: your second example, once upon a time you could write something very similar in Rust:

  do 5.times {
    // ...
  }
Where do was just sugar for calling functions that took a closure as the last argument:

  fn foo(a: A, ..., z: Z, cl: ||) { ... }

  foo(a, ..., z, || {
    ...
  })

  do foo(a, ..., z) {
    ...
  }

Re: A final proposal for Rust await syntax

#185

Earlier quoted context omitted.

Yes, "postfix" is commonly used. See http://www.cs.man.ac.uk/~pjj/cs212/fix.html or https://en.wikipedia.org/wiki/Reverse_Polish_notation

Reverse polish notation is an entirely different usage: not the same meaning as used in this proposal. It's also commonly used as the name of a piece of email software, but that's also an unrelated usage to this.

No.

RPN and postfix notation refer to the same core idea. From Wikipedia: "Reverse Polish notation (RPN), also known as Polish postfix notation or simply postfix notation, is a mathematical notation in which operators follow their operands, in contrast to Polish notation (PN), in which operators precede their operands."

Can you please explain why you wrote "Reverse polish notation is an entirely different usage"? With a citation, preferably.

Re: A final proposal for Rust await syntax

#186
post #35

> Its very easy to build a mental model of the period operator as simply the introduction of all of these various postfix syntaxes: field accesses, methods, and certain keyword operators like the await operation. (In this model, even the ? operator can be thought of as a modification on the period construct.) I like this explanation. But this whole post could really use some more concrete examples of the at the very…

My dislike for the ”dot keyword” syntax has been strong, but if it is selected, hopefully it’s at least generalized to other keywords in the future, so that `.await` doesn’t stay a lone awkward exception to what dot notation means. In particular, I wouldn’t mind if in the future `expr?` could be spelled `expr.try` for consistency (even at the expense of introducing redundancy).

[deleted]

Re: A final proposal for Rust await syntax

#187

The syntax feels a bit Ruby-ish, doesn't it? Here's an example from the article of how they could expand the syntax in the future: foo.bar(..).baz(..).match { Variant1 => { ... } Variant2(quux) => { ... } } Compared to some Ruby: 5.times { puts "Hello world!" } Note I'm by no means an expert in Ruby or Rust, this is just what I thought of when I saw the syntax.

Re: your second example, once upon a time you could write something very similar in Rust: do 5.times { // ... } Where do was just sugar for calling functions that took a closure as the last argument: fn foo(a: A, ..., z: Z, cl: ||) { ... } foo(a, ..., z, || { ... }) do foo(a, ..., z) { ... }

In fact, before the current for ... in ... syntax, this is how foreach looping used to be done:

  do some_array.each |item| {
    ...
  }

Re: A final proposal for Rust await syntax

#188
post #168

Since `await` is a keyword reserved for this purpose, could `(await expression)` ever mean anything else? What is the cost of ripping off the bandaid and starting there, as at least an alternative syntax that is consistent with the language? match expression await expression It feels like a future proposal, to allow these keywords to be chained more conveniently with a postfix. It's cool that this can possibly be gen…

I expect a proposal of this nature to pop up relatively soon. If I had to guess, I'd say the reason they're not doing this now is because they only want to choose one option for the MVP, and they've decided that they prefer this option to that option, and that the chosen option fortunately does not preclude the future option.

Also, I would expect `await` to have mandatory braces, just as `match`, `if`, `for`, etc. do.

Re: A final proposal for Rust await syntax

#189
post #18

Wow, this is the only suggestion I really didn't like. I'm really happy that it's progressing forward, but I can't help but feel that staying with the macro and postponing the decision would've been a better choice. A language should, in my opinion, not depend on syntax highlighting.

I think concerns that it depends on syntax highlighting are exaggerated. Compare `.await` to the `?` operator, both of which indicate a change in control flow. `?` does have the advantage of being a symbol which looks visually distinct even without syntax highlighting – but `.await` is much longer and thus harder to overlook entirely. Also, in practice `.await` will often be immediately followed by `?`, since async operations tend to be fallible. Since using `?` directly on a field of something is very uncommon, `.await?` acts sort of like its own unique syntactic construct with a unique visual shape, helping it stand out further.

That's assuming that you know the syntax already. If you're learning the syntax for the first time without the benefit of syntax highlighting, `.await` might be more confusing than it would otherwise be – but I think the point about `.await?`, combined with the familiarity of `await` as a special operation from other languages (as well as it just being a verb rather than a noun), would strongly hint that something different from a field access is going on. If not... well, you can always learn what it does from the documentation, since it'll be one of the first things explained in any kind of async tutorial. I'm a big believer in the concept of "strangeness budget" and avoiding unnecessary syntactic unfamiliarity, but I think the strangeness is very strongly mitigated here. In any case, most people will learn the syntax with the benefit of syntax highlighting, and IMO taking advantage of that is much more defensible than depending on syntax highlighting for readability more generally.

From a historical perspective, in the debate leading up to the switch from `try!()` to `?`, people were worried that `?` would be lost in the noise within long chains, an issue that others said would be mitigated by syntax highlighting. As it turned out, syntax highlighting does help, but `?` is also pretty distinctive without it. I think `.await` will pan out similarly.

More generally, I think that once people get used to the idea of `.await` and it stops being this new weird-looking thing, the mere-exposure effect[1] will subside and people will stop seeing confusion with field access as such a big problem. Well, people already using Rust, at any rate. Ironically, once you get past unfamiliarity, the reverse bias comes into effect, where it becomes unintuitive to think how other people first learning the language will find something weird. But from that perspective, there are a lot of weird things in Rust's syntax already. Adding more is not a good thing, but it's also not as bad as it might seem if everything in Rust seems familiar except this one thing.

[1] https://en.wikipedia.org/wiki/Mere-exposure_effect

Re: A final proposal for Rust await syntax

#190

Earlier quoted context omitted.

IMO it's awkward for the following reasons: (1) It looks like a field access, and field accesses are "cheap", method invocations aren't. This breaks the 'conceptual weight' model when you look at a line of code. Field accesses are simple and understood. It becomes impossible to gauge the 'cost' of a line by looking at it unless you're intimately familiar with the workings of 'await' and there's no visual cue. (2) If…

> there's no visual cue. There is. Your editor is going to show the await keyword in a different color. (Unless you happen to be Rob Pike.)

There's nothing else in Rust that requires me to use an editor for a semantic cue, is there? Why start here? You are correct of course, it's more a question of Rust being just as useable right now with or without syntax coloring, this small change breaks a lot.
Post reply on HN