diff --git a/quizzes/async-03-more-futures.toml b/quizzes/async-03-more-futures.toml index 867888589b..a5598f0c92 100644 --- a/quizzes/async-03-more-futures.toml +++ b/quizzes/async-03-more-futures.toml @@ -8,6 +8,7 @@ let futs: Vec<_> = [1, 2, 3].iter().map(|n| async { sleep(Duration::from_secs(5)).await; n + 1 }).collect(); + for fut in futs { let n = fut.await; println!("{n}"); @@ -26,13 +27,48 @@ id = "68680e2e-7a9f-4cee-8080-70e57fe5a2b3" [[questions]] type = "MultipleChoice" prompt.prompt = """ -Imagine Rust did not require that futures were pinned in order to be polled. Which of the following best describes the kind of problem that could occur? +Imagine Rust did not require that futures were pinned in order to be polled. +Which of the following async functions could potentially cause undefined behavior if not pinned? """ prompt.distractors = [ - "If a future were movable at any point in its lifetime, then ..." +""" +```rust +async fn example(x: &i32) -> i32 { + sleep(Duration::from_secs(1)).await; + *y +} +``` +""", +""" +```rust +async fn example(x: Vec) -> i32 { + sleep(Duration::from_secs(1)).await; + x[0] +} +``` +""", +""" +```rust +async fn example() -> i32 { + let x = 0; + sleep(Duration::from_secs(1)).await; + x +} +``` +""", ] -answer.answer = "If a future contains a reference to itself, then moving the future between polls would violate memory safety" +answer.answer = """ +```rust +async fn example(x: i32) -> i32 { + let y = &x; + sleep(Duration::from_secs(1)).await; + *y +} +``` +""" context = """ +The core problem addressed by pinning in self-reference, or a future which contains a pointer to itself. +This happens an async block contains a local variable that refers to another local variable in the future. +Here, that would be `y = &x`. """ -id = "1c3b2ad9-d9af-48b1-8cdf-bfc658ec456b" - +id = "bc8b4acb-d111-4fec-b89a-e5d1bc77c8f2" \ No newline at end of file diff --git a/quizzes/async-04-more-ways-of-combining-futures.toml b/quizzes/async-04-more-ways-of-combining-futures.toml new file mode 100644 index 0000000000..3a8f2c4d38 --- /dev/null +++ b/quizzes/async-04-more-ways-of-combining-futures.toml @@ -0,0 +1,82 @@ +[[questions]] +type = "MultipleChoice" +prompt.prompt = """ +Say you are designing a utility function with the following specification: + +> `map_stringify` takes two arguments: a vector of inputs, and an async function that converts the input to an output, +> where the outputs can be converted to strings. +> `map_stringify` returns a vector of stringified outputs. + +Which function type signature best encodes this specification? +""" +prompt.distractors = [ +""" +```rust +async fn map_stringify( + inputs: Vec, f: impl Future +) -> Vec +``` +""", +""" +```rust +fn map_stringify( + inputs: Vec, f: impl Fn(I) -> O, +) -> Vec> +where + O: ToString, +``` +""", +""" +```rust +async fn map_stringify( + inputs: Vec, f: impl Fn(I) -> F, +) -> Vec +where + F: Future + ToString, +``` +"""] +answer.answer = """ +```rust +async fn map_stringify( + inputs: Vec, f: impl Fn(I) -> F, +) -> Vec +where + O: ToString, + F: Future, +``` +""" +context = """ +Here's one implementation of the specified function: + +```rust +async fn map_stringify( + f: impl Fn(I) -> F, inputs: Vec +) -> Vec +where + O: ToString, + F: Future, +{ + let f = &f; + let futs = inputs + .into_iter() + .map(|input| async move { f(input).await.to_string() }); + futures::future::join_all(futs).await +} +``` +""" + +[[questions]] +type = "MultipleChoice" +prompt.prompt = """ +Say you are writing a program that needs to run some async code, but every 500ms check to see if the computation should be halted. +Which helper function would be most appropriate for accomplishing this task? +""" +answer.answer = "`race` / `select`" +prompt.distractors = [ + "`join`", + "`yield`", + "`spawn` / `spawn_task`" +] +context = """ +For instance, you could run a `select` in a loop between a long-running future and a sleep future that completes in 500ms. +""" diff --git a/src/ch17-04-more-ways-of-combining-futures.md b/src/ch17-04-more-ways-of-combining-futures.md index b7f50315cd..844b8d62a6 100644 --- a/src/ch17-04-more-ways-of-combining-futures.md +++ b/src/ch17-04-more-ways-of-combining-futures.md @@ -292,4 +292,7 @@ Over the last two sections, we have seen how to work with multiple futures at the same time. Up next, let’s look at how we can work with multiple futures in a sequence over time, with *streams*. +{{#quiz ../quizzes/async-04-more-ways-of-combining-futures.toml}} + + [futures]: ch17-01-futures-and-syntax.html#what-are-futures