From 58f112a213f3479710570f513557f8f480f33b52 Mon Sep 17 00:00:00 2001 From: nt54hamnghi Date: Thu, 30 Apr 2026 22:10:38 -0400 Subject: [PATCH 1/3] Explain how Rust's postfix await syntax is ergonomic --- src/part-guide/async-await.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/part-guide/async-await.md b/src/part-guide/async-await.md index 63cc24c6..366fa055 100644 --- a/src/part-guide/async-await.md +++ b/src/part-guide/async-await.md @@ -59,7 +59,7 @@ From here on in, I'm going to try to be precise about the terminology around tas An async task in Rust is just a future (usually a 'big' future made by combining many others). In other words, a task is a future which is executed. However, there are times when a future is 'executed' without being a runtime's task. This kind of a future is intuitively a *task* but not a *runtime's task*. I'll spell this out more when we get to an example of it. -## Async functions +## Async functions The `async` keyword is a modifier on function declarations. E.g., we can write `pub async fn send_to_server(...)`. An async function is simply a function declared using the `async` keyword, and what that means is that it is a function which can be executed asynchronously, in other words the caller *can choose not to* wait for the function to complete before doing something else. @@ -73,9 +73,11 @@ Within an async function, code is executed in the usual, sequential way[^preempt We stated above that a future is a computation that will be ready at some point in the future. To get the result of that computation, we use the `await` keyword. If the result is ready immediately or can be computed without waiting, then `await` simply does that computation to produce the result. However, if the result is not ready, then `await` hands control over to the scheduler so that another task can proceed (this is cooperative multitasking mentioned in the previous chapter). -The syntax for using await is `some_future.await`, i.e., it is a postfix keyword used with the `.` operator. That means it can be used ergonomically in chains of method calls and field accesses. +If you're coming from Python or JavaScript, you may be used to writing `await` before an expression, such as `await some_function()`. This is known as a prefix operator. In Rust, however, the syntax for using await is `some_future.await`, i.e., it is a postfix keyword used with the `.` operator. That means it can be used ergonomically in chains of method calls and field accesses. -Consider the following functions: +Suppose you're calling an async function that makes a network request and want to access the status code of the response. With the prefix `await` syntax, you would need to prepend `await` to `fetch()`, then wrap the expression in parentheses to access the status code, like `(await fetch()).status_code`. In Rust, you can simply write `fetch().await.status_code?`. This becomes especially helpful in longer chains. A prefix-style expression like `(await (await fetch()).json()).data` can make it hard to see what is being awaited. In Rust, the equivalent reads naturally as `fetch().await.json().await.data?`. + +Now let's look at how `async` and `await` actually behave. Consider the following functions: ```rust,norun // An async function, but it doesn't need to wait for anything. From 7de1778237d5f4f8eea74d76833c7e69a88b9d7a Mon Sep 17 00:00:00 2001 From: nt54hamnghi Date: Fri, 1 May 2026 18:03:58 -0400 Subject: [PATCH 2/3] Prioritize discussing Rust's syntax and improve clarity --- src/part-guide/async-await.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/part-guide/async-await.md b/src/part-guide/async-await.md index 366fa055..934b1bd3 100644 --- a/src/part-guide/async-await.md +++ b/src/part-guide/async-await.md @@ -73,11 +73,11 @@ Within an async function, code is executed in the usual, sequential way[^preempt We stated above that a future is a computation that will be ready at some point in the future. To get the result of that computation, we use the `await` keyword. If the result is ready immediately or can be computed without waiting, then `await` simply does that computation to produce the result. However, if the result is not ready, then `await` hands control over to the scheduler so that another task can proceed (this is cooperative multitasking mentioned in the previous chapter). -If you're coming from Python or JavaScript, you may be used to writing `await` before an expression, such as `await some_function()`. This is known as a prefix operator. In Rust, however, the syntax for using await is `some_future.await`, i.e., it is a postfix keyword used with the `.` operator. That means it can be used ergonomically in chains of method calls and field accesses. +In Rust, the syntax for using await is `some_future.await`, i.e., it is a postfix keyword used with the `.` operator. That means it can be used ergonomically in chains of method calls and field accesses. This is in contrast to languages like Python or JavaScript, where `await` is a prefix operator placed before an expression, such as `await some_function()`. -Suppose you're calling an async function that makes a network request and want to access the status code of the response. With the prefix `await` syntax, you would need to prepend `await` to `fetch()`, then wrap the expression in parentheses to access the status code, like `(await fetch()).status_code`. In Rust, you can simply write `fetch().await.status_code?`. This becomes especially helpful in longer chains. A prefix-style expression like `(await (await fetch()).json()).data` can make it hard to see what is being awaited. In Rust, the equivalent reads naturally as `fetch().await.json().await.data?`. +To see why postfix await is often more ergonomic, suppose you're calling an async function that makes a network request and want to access the status code of the response. With the prefix `await` syntax, you would need to prepend `await` to `fetch()`, then wrap the expression in parentheses to access the status code, like `(await fetch()).status_code`. In Rust, you can write `fetch().await.status_code?`. This becomes especially helpful in longer chains. E.g., an expression with two prefix awaits looks like `(await (await fetch()).json()).data`, whereas the Rust equivalent is `fetch().await.json().await.data?`, which reads more naturally. -Now let's look at how `async` and `await` actually behave. Consider the following functions: +Now let's look at how `async` and `await` in practice. Consider the following functions: ```rust,norun // An async function, but it doesn't need to wait for anything. From 3a352cc3af93683f3ed5dbc1cf66ffc1d67ca840 Mon Sep 17 00:00:00 2001 From: nt54hamnghi Date: Fri, 22 May 2026 20:50:17 -0400 Subject: [PATCH 3/3] Clarify error propagation in await examples --- src/part-guide/async-await.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/part-guide/async-await.md b/src/part-guide/async-await.md index 934b1bd3..986f46a3 100644 --- a/src/part-guide/async-await.md +++ b/src/part-guide/async-await.md @@ -75,7 +75,7 @@ We stated above that a future is a computation that will be ready at some point In Rust, the syntax for using await is `some_future.await`, i.e., it is a postfix keyword used with the `.` operator. That means it can be used ergonomically in chains of method calls and field accesses. This is in contrast to languages like Python or JavaScript, where `await` is a prefix operator placed before an expression, such as `await some_function()`. -To see why postfix await is often more ergonomic, suppose you're calling an async function that makes a network request and want to access the status code of the response. With the prefix `await` syntax, you would need to prepend `await` to `fetch()`, then wrap the expression in parentheses to access the status code, like `(await fetch()).status_code`. In Rust, you can write `fetch().await.status_code?`. This becomes especially helpful in longer chains. E.g., an expression with two prefix awaits looks like `(await (await fetch()).json()).data`, whereas the Rust equivalent is `fetch().await.json().await.data?`, which reads more naturally. +To see why postfix await is often more ergonomic, suppose you're calling an async function that makes a network request and want to access the status code of the response. With the prefix `await` syntax, you would need to prepend `await` to `fetch()`, then wrap the expression in parentheses to propagate errors with `?`, and then access the status code, like `(await fetch())?.status_code`. In postfix syntax, you can write `fetch().await?.status_code`. This becomes especially helpful in longer chains. E.g., an expression with two prefix awaits looks like `(await (await fetch())?.json())?.data`, whereas the postfix equivalent is `fetch().await?.json().await?.data`, which reads more naturally. Now let's look at how `async` and `await` in practice. Consider the following functions: