Skip to content

Commit 16d002d

Browse files
committed
Ch. 17: improve the discussion of streams
- One example compiles that I used to think didn’t. Probably the result of some renumbering. Need to check *all* of those. - Actually explain what `Context` is *for*, even though we don’t get into the details of using it. - Don’t repeat the same basic “you <verb>” form so much.
1 parent f45980a commit 16d002d

File tree

2 files changed

+48
-50
lines changed

2 files changed

+48
-50
lines changed

nostarch/chapter17.md

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,21 +1899,20 @@ help: there is a method `try_next` with a similar name
18991899
For more information about this error, try `rustc --explain E0599`.
19001900
```
19011901

1902-
As the output suggests, the problem is that we need the right trait in scope to
1903-
be able to use the `next` method. Given our discussion so far, you might
1904-
reasonably expect that to be `Stream`, but the trait we need *here* is actually
1905-
`StreamExt`. The `Ext` there is for “extension”: this is a common pattern in
1906-
the Rust community for extending one trait with another.
1907-
1908-
You might be wondering why `StreamExt` instead of `Stream`, and for that matter
1909-
whether there is a `Stream` trait at all. Briefly, the answer is that throughout
1910-
the Rust ecosystem, the `Stream` trait defines a low-level interface which
1911-
effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait
1912-
supplies a higher-level set of APIs on top of `Stream`, including the `next`
1913-
method as well as other utility methods similar to those provided by the
1914-
`Iterator` trait. We’ll return to the `Stream` and `StreamExt` traits in a
1915-
bit more detail at the end of the chapter. For now, this is enough to let us
1916-
keep moving.
1902+
As the output suggests, the reason for the compiler error is that we need the
1903+
right trait in scope to be able to use the `next` method. Given our discussion
1904+
so far, you might reasonably expect that to be `Stream`, but the trait we need
1905+
here is actually `StreamExt`. The `Ext` there is for “extension”: this is a
1906+
common pattern in the Rust community for extending one trait with another.
1907+
1908+
Why do we need `StreamExt` instead of `Stream`, and what does the `Stream` trait
1909+
itself do? Briefly, the answer is that throughout the Rust ecosystem, the
1910+
`Stream` trait defines a low-level interface which effectively combines the
1911+
`Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level
1912+
set of APIs on top of `Stream`, including the `next` method as well as other
1913+
utility methods similar to those provided by the `Iterator` trait. We’ll return
1914+
to the `Stream` and `StreamExt` traits in a bit more detail at the end of the
1915+
chapter. For now, this is enough to let us keep moving.
19171916

19181917
The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`,
19191918
as in Listing 17-31.
@@ -2109,13 +2108,13 @@ Listing 17-35: Sending messages through `tx` with an async delay without making
21092108
To sleep between messages in the `get_messages` function without blocking, we
21102109
need to use async. However, we can’t make `get_messages` itself into an async
21112110
function, because then we’d return a `Future<Output = Stream<Item = String>>`
2112-
instead of just a `Stream<Item = String>>`. The caller would have to await
2113-
`get_messages` itself to get access to the stream. But remember: everything in
2114-
a given future happens linearly; concurrency happens *between* futures.
2115-
Awaiting `get_messages` would require it to send all the messages, including
2116-
sleeping between sending each message, before returning the receiver stream. As
2117-
a result, the timeout would end up useless. There would be no delays in the
2118-
stream itself: the delays would all happen before the stream was even available.
2111+
instead of a `Stream<Item = String>>`. The caller would have to await
2112+
`get_messages` itself to get access to the stream. But remember: everything in a
2113+
given future happens linearly; concurrency happens *between* futures. Awaiting
2114+
`get_messages` would require it to send all the messages, including sleeping
2115+
between sending each message, before returning the receiver stream. As a result,
2116+
the timeout would end up useless. There would be no delays in the stream itself:
2117+
the delays would all happen before the stream was even available.
21192118

21202119
Instead, we leave `get_messages` as a regular function which returns a stream,
21212120
and spawn a task to handle the async `sleep` calls.
@@ -2557,9 +2556,10 @@ pub trait Future {
25572556
}
25582557
```
25592558

2560-
The `cx` parameter and its `Context` type is interesting, but is beyond the
2561-
scope of this chapter: you generally only need to worry about it when writing a
2562-
custom `Future` implementation.
2559+
The `cx` parameter and its `Context` type is the key to how a runtime actually
2560+
knows when to check any given future, while still being lazy. The details of how
2561+
that works are beyond the scope of this chapter, though: you generally only need
2562+
to worry about it when writing a custom `Future` implementation.
25632563

25642564
Instead, we’ll focus on the type for `self`. This is the first time we’ve seen
25652565
a method where `self` has a type annotation. A type annotation for `self` is

src/ch17-04-streams.md

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,28 +74,27 @@ help: there is a method `try_next` with a similar name
7474
For more information about this error, try `rustc --explain E0599`.
7575
```
7676

77-
As the output suggests, the problem is that we need the right trait in scope to
78-
be able to use the `next` method. Given our discussion so far, you might
79-
reasonably expect that to be `Stream`, but the trait we need *here* is actually
80-
`StreamExt`. The `Ext` there is for “extension”: this is a common pattern in
81-
the Rust community for extending one trait with another.
82-
83-
You might be wondering why `StreamExt` instead of `Stream`, and for that matter
84-
whether there is a `Stream` trait at all. Briefly, the answer is that throughout
85-
the Rust ecosystem, the `Stream` trait defines a low-level interface which
86-
effectively combines the `Iterator` and `Future` traits. The `StreamExt` trait
87-
supplies a higher-level set of APIs on top of `Stream`, including the `next`
88-
method as well as other utility methods similar to those provided by the
89-
`Iterator` trait. We’ll return to the `Stream` and `StreamExt` traits in a
90-
bit more detail at the end of the chapter. For now, this is enough to let us
91-
keep moving.
77+
As the output suggests, the reason for the compiler error is that we need the
78+
right trait in scope to be able to use the `next` method. Given our discussion
79+
so far, you might reasonably expect that to be `Stream`, but the trait we need
80+
here is actually `StreamExt`. The `Ext` there is for “extension”: this is a
81+
common pattern in the Rust community for extending one trait with another.
82+
83+
Why do we need `StreamExt` instead of `Stream`, and what does the `Stream` trait
84+
itself do? Briefly, the answer is that throughout the Rust ecosystem, the
85+
`Stream` trait defines a low-level interface which effectively combines the
86+
`Iterator` and `Future` traits. The `StreamExt` trait supplies a higher-level
87+
set of APIs on top of `Stream`, including the `next` method as well as other
88+
utility methods similar to those provided by the `Iterator` trait. We’ll return
89+
to the `Stream` and `StreamExt` traits in a bit more detail at the end of the
90+
chapter. For now, this is enough to let us keep moving.
9291

9392
The fix to the compiler error is to add a `use` statement for `trpl::StreamExt`,
9493
as in Listing 17-31.
9594

9695
<Listing number="17-31" caption="Successfully using an iterator as the basis for a stream" file-name="src/main.rs">
9796

98-
```rust,ignore,does_not_compile
97+
```rust
9998
{{#rustdoc_include ../listings/ch17-async-await/listing-17-31/src/main.rs:all}}
10099
```
101100

@@ -208,15 +207,14 @@ for 200 milliseconds, this should affect half of the messages.
208207

209208
To sleep between messages in the `get_messages` function without blocking, we
210209
need to use async. However, we can’t make `get_messages` itself into an async
211-
function, because then we’d return a `Future<Output = Stream<Item =
212-
String>>` instead of just a `Stream<Item = String>>`. The caller would have to
213-
await `get_messages` itself to get access to the stream. But remember:
214-
everything in a given future happens linearly; concurrency happens *between*
215-
futures. Awaiting `get_messages` would require it to send all the messages,
216-
including sleeping between sending each message, before returning the receiver
217-
stream. As a result, the timeout would end up useless. There would be no delays
218-
in the stream itself: the delays would all happen before the stream was even
219-
available.
210+
function, because then we’d return a `Future<Output = Stream<Item = String>>`
211+
instead of a `Stream<Item = String>>`. The caller would have to await
212+
`get_messages` itself to get access to the stream. But remember: everything in a
213+
given future happens linearly; concurrency happens *between* futures. Awaiting
214+
`get_messages` would require it to send all the messages, including sleeping
215+
between sending each message, before returning the receiver stream. As a result,
216+
the timeout would end up useless. There would be no delays in the stream itself:
217+
the delays would all happen before the stream was even available.
220218

221219
Instead, we leave `get_messages` as a regular function which returns a stream,
222220
and spawn a task to handle the async `sleep` calls.

0 commit comments

Comments
 (0)