CodeBlanks Logo Icon CodeBlanks

async block

Create an anonymous future with an async {} block.

async blocks

An async { .. } block creates a future on the spot without defining a function. With move it takes ownership of the values it captures; it's needed for futures sent to a task:

let ad = String::from("Ece");
let f = async move {
    format!("{ad} hazır")
};
// ad is now inside f
let sonuc = block_on(f);

Async blocks resemble closures but aren't called; when evaluated, they produce a future.

Async closures

To return a future from a closure, making the body an async block is enough. With Rust 1.85 the async || .. syntax became stable too:

let ikile = |x: u32| async move { x * 2 };
let f = ikile(21);          // Future
println!("{}", block_on(f)); // 42

This pattern is common when starting asynchronous work for each item in a collection.

Practice Async blocks

Create a future that captures let ad = String::from("Ece"); with an async move block and produces "Ece hazır". Also call the closure |x: u32| async move { x * 2 } with 21. Get both results with block_on and print them separated by a space.

Starter code

main.rs
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, Waker};

fn block_on<F: Future>(f: F) -> F::Output {
    let mut f = pin!(f);
    let mut cx = Context::from_waker(Waker::noop());
    loop {
        if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
            return v;
        }
    }
}

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, Waker};

fn block_on<F: Future>(f: F) -> F::Output {
    let mut f = pin!(f);
    let mut cx = Context::from_waker(Waker::noop());
    loop {
        if let Poll::Ready(v) = f.as_mut().poll(&mut cx) {
            return v;
        }
    }
}

fn main() {
    let ad = String::from("Ece");
    let f = async move { format!("{ad} hazır") };
    let ikile = |x: u32| async move { x * 2 };
    println!("{} {}", block_on(f), block_on(ikile(21)));
}

Expected output

Ece hazır 42

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 If <code>?</code> is used inside an async block, where does the error go?

  • It panics
  • It can't be used
  • To the block's own result; it doesn't exit the surrounding function Correct answer
  • It exits the surrounding function

Explanation: An async block is a separate body with its own return point; its type often needs to be stated explicitly: async { Ok::<_, String>(..) }.

2 Move ownership

Question
let ad = String::from("Ece");
let f = async ____ {
    format!("{ad} hazır")
};
Answer
let ad = String::from("Ece");
let f = async move {
    format!("{ad} hazır")
};

Explanation: async move moves the captured values into the future.

3 Syntax and result

Term Meaning
async { 1 } Future<Output = i32>
async move { ad } Owns ad
|x| async move { x * 2 } Closure returning a future
block_on(async { 7 }) 7

All lessons in Advanced