Skip to content

Commit 1a9e51d

Browse files
committed
Add a section on naming to 2996-async-iterator
1 parent 86da76c commit 1a9e51d

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

text/2996-async-iterator.md

+50
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,56 @@ async iterator implementations. The long-term fix for this, discussed in the [Fu
227227
As mentioned above, `core::async_iter` is analogous to `core::future`. But, do we want to find
228228
some other naming scheme that can scale up to other future additions, such as io traits or channels?
229229

230+
## Naming
231+
232+
When considering what to name the trait and concepts, there were two options:
233+
234+
- __`Stream`:__ with prior art in `futures-rs`, runtimes, and much of the
235+
of the async ecosystem.
236+
- __`AsyncIterator`:__ which follows the pattern established of prefixing
237+
the async version of another trait with `Async` in the ecosystem. For example
238+
[`AsyncRead`](https://docs.rs/futures-io/latest/futures_io/trait.AsyncRead.html)
239+
is an async version of [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html).
240+
241+
We ended up choosing `AsyncIterator` over `Stream` for a number of reasons:
242+
243+
1. It provides consistency between async and non-async Rust. Prefixing the async
244+
version of an existing trait with `Async` helps with discoverability, and teaching
245+
how APIs relate to each other. For example in this RFC we describe
246+
`AsyncIterator` as "an async version of `Iterator`".
247+
2. The word "stream" is fairly established terminology within computing: it
248+
commonly refers to a type which yields data repeatedly. Traits such as
249+
`Iterator`, `Read`, and `Write` are often referred to as "streams" or
250+
"streaming". Naming a single trait `Stream` can lead to confusion, as it is not
251+
the only trait which streams.
252+
3. `std::net::TcpStream` does not in fact implement `Stream`, despite the name
253+
suggesting it might. In the ecosystem async versions of `TcpStream` don't either:
254+
`Async{Read,Write}` are used instead. This can be confusing.
255+
256+
Additionally, there is prior art in other languages for using an
257+
"iterator"/"async iterator" naming scheme:
258+
259+
- JavaScript: [`Symbol.Iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator)
260+
and [`Symbol.AsyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator)
261+
- C#: [`IEnumerable`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ienumerable-1?view=net-5.0)
262+
and [`IAsyncEnumerable`](https://docs.microsoft.com/en-us/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8)
263+
- Python: [`__iter__`](https://wiki.python.org/moin/Iterator)
264+
and [`__aiter__`](https://www.python.org/dev/peps/pep-0525/)
265+
- Swift: [`Sequence`](https://developer.apple.com/documentation/swift/sequence)
266+
and [`AsyncSequence`](https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md)
267+
268+
Despite being a clearer in many regards, the name `AsyncIterator` loses to
269+
`Stream` in terms of brevity. `AsyncIterator` / `async_iter` / "async iterator"
270+
is longer to write than `stream` in every instance.
271+
272+
Additionally the Rust ecosystem has a multi-year history of using `Stream` to
273+
describe the concept of "async iterators". But we expect that as
274+
`AsyncIterator` becomes the agreed upon terminology to refer to "async iterators",
275+
the historical benefit of using "stream" terminology will lessen over time.
276+
277+
Overall we found that despite having some downsides, the name `AsyncIterator`
278+
is strongly preferable over `Stream`.
279+
230280
# Future possibilities
231281
[future-possibilities]: #future-possibilities
232282

0 commit comments

Comments
 (0)