# SE-0388: Convenience Async\[Throwing\]Stream.makeStream methods

**URL:** <https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139>\
**Category:** Proposal Reviews\
**Tags:** concurrency, stdlib, asyncsequence\
**Created:** [February 15, 2023, 5:47pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139 "2023-02-15T17:47:34Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [February 15, 2023, 5:47pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/1 "2023-02-15T17:47:34Z")

</div>

Hello Swift community,

The review of "Convenience Async[Throwing]Stream.makeStream methods" begins now and runs through February 26, 2023. The proposal is available here:

> [swift-evolution/proposals/0388-async-stream-factory.md at main · swiftlang/swift-evolution · GitHub](https://github.com/apple/swift-evolution/blob/main/proposals/0388-async-stream-factory.md)

To assist in your review, I've prepared toolchains for [macOS](https://ci.swift.org/job/swift-PR-toolchain-macos/566/artifact/branch-main/swift-PR-62968-566-osx.tar.gz), [Ubuntu 20.04](https://download.swift.org/tmp/pull-request/62968/352/ubuntu2004/PR-ubuntu2004.tar.gz), and [Windows 10](https://ci-external.swift.org/job/swift-PR-build-toolchain-windows/444/artifact/build/artifacts/installer.exe) which include the proposal's implementation.

Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to the review manager by [email](mailto:beccadax@apple.com). When emailing the review manager directly, please keep the proposal link at the top of the message and put "SE-0388" in the subject line.

##### What goes into a review?

The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:

- What is your evaluation of the proposal?
- Is the problem being addressed significant enough to warrant a change to Swift?
- Does this proposal fit well with the feel and direction of Swift?
- If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
- How much effort did you put into your review? A glance, a quick reading, or an in-depth study?

More information about the Swift evolution process is available at

> [https://github.com/apple/swift-evolution/blob/main/process.md](https://github.com/apple/swift-evolution/blob/main/process.md)

Happy reviewing,

Becca Royal-Gordon  
SE-0388 Review Manager

---

<div class="post-metadata">

**Author:** ![rauhul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rauhul/32/35207_2.png) [@rauhul](https://forums.swift.org/u/rauhul)\
**Post date:** [February 15, 2023, 6:11pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/2 "2023-02-15T18:11:32Z")

</div>

+1 I have the following snippet in a code base I maintain and would love to remove it.

```swift
Extensions/AsyncStream+Init.swift
10: public static func initEscapingContinuation(

```

I think using a type over a tuple makes sense, the only thing that strikes me as odd is the name "NewStream" as `AsyncStream<T>.init()` also produces a new stream.

Would this type/methods be marked as `@_backDeployed` so folks like myself can remove our versions of this api?

---

<div class="post-metadata">

**Author:** ![willft](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/willft/32/412_2.png) [@willft](https://forums.swift.org/u/willft)\
**Post date:** [February 15, 2023, 6:16pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/3 "2023-02-15T18:16:08Z")

</div>

Yes please! I find the current API extremely annoying in most cases (though there are some cases where it makes sense, it’s just not the majority of my usage). The code sample in the motivation section is a perfect example of the annoying issues I run into with this API.

I will also say that when I first came to this API I found it very unintuitive that the continuation was allowed to escape the closure, since I can think of no other “make a thing which is passed into a trailing closure” API in the standard library that allows escaping the “thing passed in.”

On the alternatives considered:

- I personally don’t care about returning a tuple or having a named type for it; both seem reasonable.
- Strongly agree with the proposal that NewStream should not have an `init` (what a weird shape for the API that would be)
- Strongly agree that AsyncStream.init should not take a continuation — you shouldn’t be able to tie random continuations & streams together, and you shouldn’t be able to get a continuation that doesn’t go to any stream.

I did a light reading of the proposal, and have used these types before.

---

<div class="post-metadata">

**Author:** ![FranzBusch](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/franzbusch/32/19447_2.png) [@FranzBusch](https://forums.swift.org/u/FranzBusch)\
**Post date:** [February 15, 2023, 6:16pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/4 "2023-02-15T18:16:21Z")

</div>

> [@rauhul](#):
>
> I think using a type over a tuple makes sense, the only thing that strikes me as odd is the name "NewStream" as `AsyncStream<T>.init()` also produces a new stream.

Naming is hard 😃 I went with the same name that we used in [NIO](https://github.com/apple/swift-nio/blob/ab43dc6949c4197155fff08d1e3438ddba0060a1/Sources/NIOCore/AsyncSequences/NIOAsyncSequenceProducer.swift#L108). Open to better suggestions though!

> [@rauhul](#):
>
> Would this type/methods be marked as `@_backDeployed` so folks like myself can remove our versions of this api?

[SE-0376](https://github.com/apple/swift-evolution/blob/main/proposals/0376-function-back-deployment.md) only allows for functions to be back deployed. Since we are introducing a new type here we cannot back deploy this function. This is the big upside of using the tuple since it allows us to back deploy this.

---

<div class="post-metadata">

**Author:** ![rauhul](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rauhul/32/35207_2.png) [@rauhul](https://forums.swift.org/u/rauhul)\
**Post date:** [February 15, 2023, 6:21pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/5 "2023-02-15T18:21:59Z")

</div>

> [@FranzBusch](#):
>
> Naming is hard 😃 I went with the same name that we used in [NIO](https://github.com/apple/swift-nio/blob/ab43dc6949c4197155fff08d1e3438ddba0060a1/Sources/NIOCore/AsyncSequences/NIOAsyncSequenceProducer.swift#L108). Open to better suggestions though!

Not sure this is actually a better suggestion, but my default would be to name it as it is on the tin: "StreamAndContinuation".

> [@FranzBusch](#):
>
> [SE-0376](https://github.com/apple/swift-evolution/blob/main/proposals/0376-function-back-deployment.md) only allows for functions to be back deployed. Since we are introducing a new type here we cannot back deploy this function. This is the big upside of using the tuple since it allows us to back deploy this.

I definitely forgot about this restriction. Regardless, I do still think using a type is better in the long term and hoping for a solution to type back deployment later.

---

<div class="post-metadata">

**Author:** ![mtsrodrigues](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mtsrodrigues/32/34169_2.png) [@mtsrodrigues](https://forums.swift.org/u/mtsrodrigues)\
**Post date:** [February 15, 2023, 6:59pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/6 "2023-02-15T18:59:55Z")

</div>

+1 That looks great! But I think the name `NewStream` sounds too generic. Maybe `StreamWithContinuation` or `StreamContinuationPair`? 🤔

---

<div class="post-metadata">

**Author:** ![mtsrodrigues](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mtsrodrigues/32/34169_2.png) [@mtsrodrigues](https://forums.swift.org/u/mtsrodrigues)\
**Post date:** [February 15, 2023, 7:11pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/7 "2023-02-15T19:11:26Z")

</div>

> [@FranzBusch](#):
>
> This is the big upside of using the tuple since it allows us to back deploy this.

Couldn't both versions be included with the one returning a tuple marked with **backDeployed** and **\_disfavoredOverload**?

---

<div class="post-metadata">

**Author:** ![gregcotten](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/gregcotten/32/13288_2.png) [@gregcotten](https://forums.swift.org/u/gregcotten)\
**Post date:** [February 15, 2023, 7:23pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/8 "2023-02-15T19:23:20Z")

</div>

+1, this is a great addition, and sorely needed!

It definitely makes sense to add this to the stdlib - I see so many people doing the same boilerplate with the implicitly unwrapped `AsyncStream<T>.Continuation`!

---

<div class="post-metadata">

**Author:** ![JuneBash](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/junebash/32/19323_2.png) [@JuneBash](https://forums.swift.org/u/JuneBash)\
**Post date:** [February 15, 2023, 7:30pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/9 "2023-02-15T19:30:45Z")

</div>

I'm a big +0.9 on this. I think this fills an obvious gap in current APIs, but also I think we could potentially bikeshed on the name `NewStream` a little bit. Maybe `WithContinuation`? (ie `AsyncStream<Element>.WithContinuation`)

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [February 15, 2023, 8:27pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/10 "2023-02-15T20:27:40Z")

</div>

Any version of the functionality seems fine to me, however the alternative variant using a function could potentially be back ported for convenience via the `@_alwaysEmitIntoClient` (if it applies to static functions as well).

If we‘re bikeshedding, then `AsyncStream<…>.detached` could be another option as we‘re detaching the the streams continuation from the otherwise encapsulated build closure .

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [February 15, 2023, 8:29pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/11 "2023-02-15T20:29:03Z")

</div>

> [@rauhul](#):
>
> I definitely forgot about this restriction. Regardless, I do still think using a type is better in the long term and hoping for a solution to type back deployment later.

i've written and deleted such a type many times in the past and my conclusion has always been that it doesn't serve much purpose other than to glue two things together, which tuples do just as well.

the purpose of a type is to host API that wouldn't make sense to place anywhere else. the proposed `NewStream` type doesn’t have any API.

perhaps it would be useful to have `NewStream` if it had an init that could be accessed with leading dot syntax. but the proposal seems to have [explicitly ruled that out](https://github.com/apple/swift-evolution/blob/main/proposals/0388-async-stream-factory.md#expose-an-initializer-on-the-newstream-type). so as it stands i feel that the new type serves no purpose.

i think a tuple return is better for this API.

---

<div class="post-metadata">

**Author:** ![hassila](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/hassila/32/22647_2.png) [@hassila](https://forums.swift.org/u/hassila)\
**Post date:** [February 15, 2023, 8:39pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/12 "2023-02-15T20:39:40Z")

</div>

+1 - allows us to drop a helper.

Our internal solution for this uses a tuple, but as was pointed out during the pitch a type allows for better documentation and discoverability which is nice (which would make me support the type). (Regardless, would be +1 for the tuple variation too, it works fine for us now)

I’d agree with the suggestion for bikeshedding the naming a bit - WithContinuation as suggested by @JuneBash probably the best suggestion so far.

---

<div class="post-metadata">

**Author:** ![tcldr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tcldr/32/24405_2.png) [@tcldr](https://forums.swift.org/u/tcldr)\
**Post date:** [February 15, 2023, 8:51pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/13 "2023-02-15T20:51:50Z")

</div>

+1 Overall.

Naming is definitely awkward though.

I would say I prefer the tuple over introducing a new type. I think the documentation argument is negated by the simplicity of the type.

AsyncStream, AsyncStream.Continuation, and makeStream can all be documented so not sure what else is needed here. Seems crystal clear.

It also seems to be the API a bunch of people have come up with completely independently and organically which suggests it’s a natural fit.

If there _must_ be a type, I think StreamContinuationPair says all it needs to.

---

<div class="post-metadata">

**Author:** ![Sajjon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sajjon/32/12044_2.png) [@Sajjon](https://forums.swift.org/u/Sajjon)\
**Post date:** [February 15, 2023, 8:58pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/14 "2023-02-15T20:58:17Z")

</div>

+1  
No brainer, should have been included from the start, but we all work iteratively :)

---

<div class="post-metadata">

**Author:** ![bzamayo](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/bzamayo/32/764_2.png) [@bzamayo](https://forums.swift.org/u/bzamayo)\
**Post date:** [February 15, 2023, 9:24pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/15 "2023-02-15T21:24:41Z")

</div>

+1. I don't really see the need for a type here, though, unless we expect the `NewStream` type to gain additional API over time — which I don't think we do? A tuple with labels seems perfectly suited for this use case. I don't find the documentation argument holds much weight; the documentation comments shown in the code snippets are short enough they can happily live as part of the `makeStream` method.

(The back-deployability of the tuple approach is an added bonus.)

---

<div class="post-metadata">

**Author:** ![critz](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/critz/32/11603_2.png) [@critz](https://forums.swift.org/u/critz)\
**Post date:** [February 15, 2023, 9:43pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/16 "2023-02-15T21:43:42Z")

</div>

This feature addresses a strong need. Thank you for addressing it.

Reading the example, I’d change…

```swift
for await i in newStream.stream {
      print(i)
    } 

```

…To…

```swift
 for await i in newStream.values {
      print(i)
    }

```

Or maybe `newStream.elements` or `newStream.items`.

I often hear this paradigm as “values over time”.

---

<div class="post-metadata">

**Author:** ![twittemb](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/twittemb/32/28643_2.png) [@twittemb](https://forums.swift.org/u/twittemb)\
**Post date:** [February 15, 2023, 10:29pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/17 "2023-02-15T22:29:36Z")

</div>

Definitely needed.

I would suggest a name like `AsyncStream.pipe()`. Returning either a tuple, or a type `AsyncStreamPipe`.

Pipe fits well with the idea of connecting an input (the continuation), to an output (the stream per se), Plus this already is a word used in the Unix world right?

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [February 15, 2023, 10:53pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/18 "2023-02-15T22:53:01Z")

</div>

```swift
withoutSpeakingAsReviewManager {

```

> [@bzamayo](#):
>
> I don't really see the need for a type here, though, unless we expect the `NewStream` type to gain additional API over time — which I don't think we do? A tuple with labels seems perfectly suited for this use case. I don't find the documentation argument holds much weight; the documentation comments shown in the code snippets are short enough they can happily live as part of the `makeStream` method.

I haven't decided where I come down on the result type question, but I'd like to point out a third alternative: make `NewStream` a `typealias` for a tuple. This would have the back-deployment\* and destructuring advantages of a tuple, but would still allow us to attach documentation to the typealias (just not the individual properties).

_\* Unlike structs and other nominal types, typealiases are resolved at compile time and have no ABI, so they don't prevent back-deployment._

```swift
}

```

---

<div class="post-metadata">

**Author:** ![mayoff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mayoff/32/613_2.png) [@mayoff](https://forums.swift.org/u/mayoff)\
**Post date:** [February 15, 2023, 11:36pm UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/19 "2023-02-15T23:36:14Z")

</div>

Looks like a great addition to the standard library.

The `NewStream` name seems a little redundant (`AsyncStream.NewStream`) and yet insufficient. I think something like `Endpoints` would work better, as the object contains both the read endpoint (the `AsyncStream`) and the write endpoint (the `Continuation`).

---

<div class="post-metadata">

**Author:** ![sindresorhus](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sindresorhus/32/1677_2.png) [@sindresorhus](https://forums.swift.org/u/sindresorhus)\
**Post date:** [February 16, 2023, 5:40am UTC](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139/20 "2023-02-16T05:40:30Z")

</div>

+1 in general, but I would prefer a tuple over a type. I already use a similar helper in my own projects which uses a tuple with labels and that works great. I don't buy the documentation argument and a new type also comes with downsides like not being able to backdeploy.

* * *

> make NewStream a typealias for a tuple.

I personally don't think a typealias is even needed. The tuple elements can just be documented on the `makeStream()` method.

[Next page](https://forums.swift.org/t/se-0388-convenience-async-throwing-stream-makestream-methods/63139.md?page=2)
