Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AsyncSequenceとAsyncStreamのプロポーザルを全部読む!!

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 AsyncSequenceとAsyncStreamのプロポーザルを全部読む!!

Avatar for Shigure Shimotori

Shigure Shimotori

November 02, 2025
Tweet

More Decks by Shigure Shimotori

Other Decks in Programming

Transcript

  1. ଟ͍ʙ • SE-0298 Async/Await: Sequences • SE-0314 AsyncStream and AsyncThrowingStream

    • SE-0388 Convenience Async[Throwing]Stream.makeStream methods • SE-0406 Backpressure support for AsyncStream • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  2. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences • SE-0314 AsyncStream and AsyncThrowingStream

    • SE-0388 Convenience Async[Throwing]Stream.makeStream methods • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  3. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences • SE-0314 AsyncStream and AsyncThrowingStream

    • SE-0388 Convenience Async[Throwing]Stream.makeStream methods • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  4. SE-0298 • https://github.com/swiftlang/swift-evolution/blob/main/proposals/0298- asyncsequence.md • Swift 5.5ʢ2021೥ʣ • iOS 13.0΁ͷόοΫϙʔτ͋Γ

    • λΠτϧ΍ϑΝΠϧ໊ͷ௨ΓAsyncSequenceͷ࿩ https://developer.apple.com/documentation/Swift/AsyncSequence
  5. ͜Εͷ͜ͱͰ͢ʂ • ͳΜ͔Α͘for awaitจͰ͙Δ͙Δճ͞ΕͯΔ΍ͭ for try await line in myFile.lines()

    { // Do something with each line } https://developer.apple.com/documentation/Swift/AsyncSequence ͜Ε
  6. SE-0298 Async/Await: Sequences • ࣌ؒͷܦաͱͱ΋ʹෳ਺ͷ஋Λฦ͢ for try await line in

    myFile.lines() { // Do something with each line } https://github.com/swiftlang/swift-evolution/blob/main/proposals/0298-asyncsequence.md
  7. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences ✅ • SE-0314 AsyncStream and

    AsyncThrowingStream • SE-0388 Convenience Async[Throwing]Stream.makeStream methods • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  8. SE-0314 • https://github.com/swiftlang/swift-evolution/blob/main/proposals/0314- async-stream.md • Swift 5.5ʢ2021೥ʣ • iOS 13.0΁ͷόοΫϙʔτ͋Γ

    • λΠτϧ΍ϑΝΠϧ໊ͷ௨ΓAsyncStreamͷ࿩ https://developer.apple.com/documentation/Swift/AsyncStream
  9. init(_:bufferingPolicy:_:) class QuakeMonitor { var quakeHandler: ((Quake) -> Void)? func

    startMonitoring() { ... } func stopMonitoring() { ... } static var quakes: AsyncStream<Quake> { AsyncStream { continuation in let monitor = QuakeMonitor() monitor.quakeHandler = { quake in continuation.yield(quake) } continuation.onTermination = { @Sendable _ in monitor.stopMonitoring() } monitor.startMonitoring() } } } https://developer.apple.com/documentation/Swift/AsyncStream ͜Ε
  10. Continuationͩʂ • withCheckedContinuation { continuation in } ͬͯ΍ͭ func withCheckedContinuation<T>(

    _ body: (CheckedContinuation<T, Never>) -> Void ) async -> sending T https://developer.apple.com/documentation/swift/withcheckedcontinuation(isolation:function:_:)
  11. ܧଓ……ʁ class QuakeMonitor { var quakeHandler: ((Quake) -> Void)? func

    startMonitoring() { ... } func stopMonitoring() { ... } static var quakes: AsyncStream<Quake> { AsyncStream { continuation in let monitor = QuakeMonitor() monitor.quakeHandler = { quake in continuation.yield(quake) } continuation.onTermination = { @Sendable _ in monitor.stopMonitoring() } monitor.startMonitoring() } } } https://developer.apple.com/documentation/Swift/AsyncSequence
  12. class QuakeMonitor { var quakeHandler: ((Quake) -> Void)? func startMonitoring()

    { ... } func stopMonitoring() { ... } static var quakes: AsyncStream<Quake> { AsyncStream { continuation in let monitor = QuakeMonitor() monitor.quakeHandler = { quake in continuation.yield(quake) } continuation.onTermination = { @Sendable _ in monitor.stopMonitoring() } monitor.startMonitoring() } } } AsyncStream { continuation in continuation.yield(quake) continuation.onTermination = { } } Continuationͩʂ https://developer.apple.com/documentation/Swift/AsyncSequence AsyncStream.Continuation
  13. Haskellͷunfolding • unfoldr :: (b -> Maybe (a, b)) ->

    b -> [a] • SwiftͰॻ͘ͱ
 func unfoldr<T, U>(f: (U) -> (T, U)?, seed: U) -> [T] • SwiftͬΆ͘આ໌͢Δͱ
 Ϋϩʔδϟ͸γʔυ஋seedΛड͚औΓɺArrayͷੜ੒͕׬͍ྃͯ͠Ε͹nil Λฦ͢ɻͦ͏Ͱͳ͚Ε͹(t, u)Λฦ͠ɺt͸Arrayͷઌ಄ʹ௥Ճ͞Εɺu͸࣍ ͷ࠶ؼݺͼग़͠Ͱ࢖͏γʔυ஋ͱͳΔɻ • c.f. HaskellͷfoldrɺSwiftͷreduce(_:_:) https://hackage.haskell.org/package/base-4.21.0.0/docs/Data-List.html#v:unfoldr
  14. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences ✅ • SE-0314 AsyncStream and

    AsyncThrowingStream ✅ • SE-0388 Convenience Async[Throwing]Stream.makeStream methods • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  15. SE-0388 • https://github.com/swiftlang/swift-evolution/blob/main/proposals/0388- async-stream-factory.md • Swift 5.9ʢ2023೥ʣ • iOS 13.0΁ͷόοΫϙʔτ͋Γ

    • AsyncStreamͷmakeStream(of:bufferingPolicy:)ͷ࿩ https://developer.apple.com/documentation/swift/asyncstream/makestream(of:bu ff eringpolicy:)
  16. ͜Εͷ͜ͱͰ͢ʂ let (stream, continuation) = AsyncStream.makeStream(of: Int.self) await withTaskGroup(of: Void.self)

    { group in group.addTask { for i in 0...9 { continuation.yield(i) } continuation.finish() } group.addTask { for await i in stream { print(i) } } } ͜Ε
  17. class QuakeMonitor { var quakeHandler: ((Quake) -> Void)? func startMonitoring()

    { ... } func stopMonitoring() { ... } static var quakes: AsyncStream<Quake> { AsyncStream { continuation in let monitor = QuakeMonitor() monitor.quakeHandler = { quake in continuation.yield(quake) } continuation.onTermination = { @Sendable _ in monitor.stopMonitoring() } monitor.startMonitoring() } } } AsyncStream { continuation in continuation.yield(quake) continuation.onTermination = { } } Continuationͩʂʢ࠶ʣ https://developer.apple.com/documentation/Swift/AsyncSequence
  18. ετϦʔϜͱܧଓͷ྆ํΛฦ͢ʂ let (stream, continuation) = AsyncStream.makeStream(of: Int.self) await withTaskGroup(of: Void.self)

    { group in group.addTask { for i in 0...9 { continuation.yield(i) } continuation.finish() } group.addTask { for await i in stream { print(i) } } }
  19. ؾʹͳΔ… let (stream, continuation) = AsyncStream.makeStream(of: Int.self) await withTaskGroup(of: Void.self)

    { group in group.addTask { for i in 0...9 { continuation.yield(i) } continuation.finish() } group.addTask { for await i in stream { print(i) } } } ໭Γ஋͕௝͘͠λϓϧ
  20. ͦΕͧΕߦ͖ઌ͕ҧ͏ʂ let (stream, continuation) = AsyncStream.makeStream(of: Int.self) await withTaskGroup(of: Void.self)

    { group in group.addTask { for i in 0...9 { continuation.yield(i) } continuation.finish() } group.addTask { for await i in stream { print(i) } } } ܧଓ͸producer͕࢖͏ ετϦʔϜ͸consumer͕࢖͏
  21. όοΫϙʔτ͞Εͨྫ • Swift Concurrency • viewIsAppearing(_:) • ͱ͔ • ৄ͘͠͸ڈ೥ͷiOSDC

    Japanͷauramagi͞ΜͷൃදΛ͝ཡ͍ͩ͘͞ https://fortee.jp/iosdc-japan-2024/proposal/f30647c8-dd78-4853-8718-7bcb856b1239
 https://www.docswell.com/s/usami-k/5M1P4L-uiviewcontroller-viewisappearing
  22. ೥ද • 2021೥9݄ Swift 5.5ͰSwift ConcurrencyσϏϡʔ • 2021೥12݄ Xcode 13.2ͰSwift

    Concurrency͕iOS 13.0΁όοΫϙʔτ͞ΕΔ • 2023೥3݄ Swift 5.8Ͱ@backDeployed͕௥Ճ͞ΕΔ • 2023೥9݄ Swift 5.9ͰmakeStream͕௥Ճ͞ΕΔɺόοΫσϓϩΠ΋͞ΕΔ https://speakerdeck.com/satotakeshi/swift-concurrencyru-men
 https://team-blog.mitene.us/%E5%AE%B6%E6%97%8F%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0-%E3%81%BF%E3%81%A6%E3%81%AD-%E3%81%ABswift- concurrency%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-1bafc45ab3f3
  23. ೥ද • 2021೥9݄ Swift 5.5ͰSwift ConcurrencyσϏϡʔ • 2021೥12݄ Xcode 13.2ͰSwift

    Concurrency͕iOS 13.0΁όοΫϙʔτ͞ΕΔ • 2023೥3݄ Swift 5.8Ͱ@backDeployed͕௥Ճ͞ΕΔ • 2023೥9݄ Swift 5.9ͰmakeStream͕௥Ճ͞ΕΔɺόοΫσϓϩΠ΋͞ΕΔ https://speakerdeck.com/satotakeshi/swift-concurrencyru-men
 https://team-blog.mitene.us/%E5%AE%B6%E6%97%8F%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0-%E3%81%BF%E3%81%A6%E3%81%AD-%E3%81%ABswift- concurrency%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-1bafc45ab3f3 👇ʁʁʁʁʁ👆
  24. ೥ද • 2021೥9݄ Swift 5.5ͰSwift ConcurrencyσϏϡʔ • 2021೥12݄ Xcode 13.2ͰSwift

    Concurrency͕iOS 13.0΁όοΫϙʔτ͞ΕΔ • 2023೥3݄ Swift 5.8Ͱ@backDeployed͕௥Ճ͞ΕΔʢSE-0376ʣ • 2023೥9݄ Swift 5.9ͰmakeStream͕௥Ճ͞ΕΔɺόοΫσϓϩΠ΋͞ΕΔ https://speakerdeck.com/satotakeshi/swift-concurrencyru-men
 https://team-blog.mitene.us/%E5%AE%B6%E6%97%8F%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0-%E3%81%BF%E3%81%A6%E3%81%AD-%E3%81%ABswift- concurrency%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-1bafc45ab3f3
  25. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences ✅ • SE-0314 AsyncStream and

    AsyncThrowingStream ✅ • SE-0388 Convenience Async[Throwing]Stream.makeStream methods ✅ • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  26. ͜Ε͕૿͑·ͨ͠ʂ protocol AsyncIteratorProtocol<Element, Failure> { associatedtype Failure: Error = any

    Error mutating func next( isolation actor: isolated (any Actor)? ) async throws(Failure) -> Element? }
  27. ͜Εͷ͜ͱͰ͢ʂʢ࠶ʣ protocol AsyncIteratorProtocol<Element, Failure> { associatedtype Failure: Error = any

    Error mutating func next( isolation actor: isolated (any Actor)? ) async throws(Failure) -> Element? }
  28. Primary associated typeͰͰ͖Δ͜ͱ • 👇͕࣮૷Ͱ͖Δ extension AsyncSequence { public func

    map<Transformed>( _ transform: @Sendable @escaping (Element) async throws -> Transformed ) -> some AsyncSequence<Transformed, any Error> { ... } } ΊͬͪΌmap΍ fi lterΛͯ͠΋ೖΕࢠʹͳΒͳ͍🎉 ※ඪ४ϥΠϒϥϦͷmap(_:)ͷ໭Γ஋ͷܕ͸૬มΘΒͣAsyncThrowingMapSequence ࣗ෼Ͱsome AsyncSequenceʹ͠Α͏ʂ
  29. ίϯύΠϥ͕ݕ஌͢Δํ๏ • AsyncSequence΍AsyncSequenceIteratorࣗମʹ@rethrows͕͍ͭͯͨ • աڈܗ @rethrows public protocol AsyncSequence {

    @rethrows public protocol AsyncIteratorProtocol { https://github.com/swiftlang/swift/blob/9067148bc9c9a72730dbeebef32965b3aaeb34fb/stdlib/public/Concurrency/AsyncSequence.swift#L75-L76
 https://github.com/swiftlang/swift/blob/9067148bc9c9a72730dbeebef32965b3aaeb34fb/stdlib/public/Concurrency/AsyncIteratorProtocol.swift#L90-L91
  30. @rethrows protocol • Experimental featureʢͩͬͨΒ͍͠ʣ • some AsyncSequenceͱซ༻͍͕ͨͦ͠͏͢Δͱ@rethrows͕ػೳ͠ͳ͍ • ͳͷͰSwift

    6.0͔Β@rethrowsΛ࢖͏ͷΛ΍ΊͨͬΆ͍ • ৄ͘͠͸Point-Freeͷهࣄɺ΋͘͠͸ڈ೥ͷtreastrain͞Μͷൃද https://github.com/swiftlang/swift/commit/bb7a563e6c7756dc6c3c910db7ecacab2e1698b7
 https://fortee.jp/iosdc-japan-2024/proposal/c0c62dc1-992c-4d9f-8812-02994593d96c
 https://www.pointfree.co/blog/posts/73-parser-errors
  31. ӽ͑Δͱ͖ͬͯͲΜͳͱ͖ @MainActor func iterate(over stream: AsyncStream<Int>) async { var iterator

    = stream.makeAsyncIterator() while let element = await iterator.next() { // do something with 'element' } } https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md
  32. ӽ͑Δͱ͖ͬͯͲΜͳͱ͖ @MainActor func iterate(over stream: AsyncStream<Int>) async { var iterator

    = stream.makeAsyncIterator() while let element = await iterator.next() { // do something with 'element' } } warning:
 passing argument of non-sendable type 'inout AsyncStream<Int>.Iterator'
 outside of main actor-isolated context may introduce data races https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md
  33. ӽ͑Δͱ͖ͬͯͲΜͳͱ͖ @MainActor func iterate(over stream: AsyncStream<Int>) async { var iterator

    = stream.makeAsyncIterator() while let element = await iterator.next() { // do something with 'element' } } ؔ਺ࣗମ͸MainActorʹִ཭͞ΕͯΔ ͍ͭ͜͸nonisolated https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md
  34. ӽ͑Δͱ͖ͬͯͲΜͳͱ͖ @MainActor func iterate(over stream: AsyncStream<Int>) async { var iterator

    = stream.makeAsyncIterator() while let element = await iterator.next() { // do something with 'element' } } next()ͷҾ਺ͱ໭Γ஋Ͱ͋Δ͜ͷ2ͭ͸ڥքΛӽ͑Δ͜ͱʹͳΔ https://github.com/swiftlang/swift-evolution/blob/main/proposals/0420-inheritance-of-actor-isolation.md
  35. AsyncIteratorProtocolͱisolation ʢ6.0Ҏ্ͷ࣌ʣ • #isolationΛड͚औΕΔΑ͏ͳnextϝιου͕͋Δ • func next(isolation actor: isolated (any

    Actor)?) • SE-0414 Region based isolationͷ໊લ͕ग़͍ͯΔ͕ɺ
 SE-0414͕͜ͷ໰୊Λղܾ͍ͯ͠ΔΘ͚Ͱ͸ͳ͍ɾɾͱࢥ͏ next(isolation: #isolation)Λۦ࢖͢Δ͜ͱͰɺRegion based isolationΛՃຯͨ͠ݱࡏͷconcurrency checkΛύε͠Α͏ͶɺͱಡΊͳ͍͜ͱ΋ͳ͍
  36. AsyncIteratorProtocolͱisolation ʢ6.0Ҏ্ͷ࣌ʣ • #isolationΛड͚औΕΔΑ͏ͳnextϝιου͕͋Δ • func next(isolation actor: isolated (any

    Actor)?) • SE-0414 Region based isolationͷ໊લ͕ग़͍ͯΔ͕ɺ
 SE-0414͕͜ͷ໰୊Λղܾ͍ͯ͠ΔΘ͚Ͱ͸ͳ͍ɾɾͱࢥ͏ next(isolation: #isolation)Λۦ࢖͢Δ͜ͱͰɺRegion based isolationΛՃຯͨ͠ݱࡏͷconcurrency checkΛύε͠Α͏ͶɺͱಡΊͳ͍͜ͱ΋ͳ͍ SE-0313ʢSwift 5.5ʣ͔Β͋Δ
  37. AsyncIteratorProtocolͱisolation ʢ6.0Ҏ্ͷ࣌ʣ • #isolationΛड͚औΕΔΑ͏ͳnextϝιου͕͋Δ • func next(isolation actor: isolated (any

    Actor)?) • SE-0414 Region based isolationͷ໊લ͕ग़͍ͯΔ͕ɺ
 SE-0414͕͜ͷ໰୊Λղܾ͍ͯ͠ΔΘ͚Ͱ͸ͳ͍ɾɾͱࢥ͏ next(isolation: #isolation)Λۦ࢖͢Δ͜ͱͰɺRegion based isolationΛՃຯͨ͠ݱࡏͷconcurrency checkΛύε͠Α͏ͶɺͱಡΊͳ͍͜ͱ΋ͳ͍ non-isolatedΛදݱ͢ΔͨΊʹඞཁ ݺͼग़͠ଆͷִ཭
  38. Ͱɺpolymorphism͕ͳΜͩͬͯʁ • Polymorphismͷجຊతͳҙຯ͸ɺʮ1 ͭͷؔ਺ (͋Δ͍͸ϝιουɺࣜͳͲ) ͕ɺ༷ʑͳܕΛ΋ͭҾ਺ʹద༻Ͱ͖Δʯͱ͍͏ҙຯ by ஜ೾େֶतۀ https://www.cs.tsukuba.ac.jp/~kam/lecture/plm2010/12.pdf protocol

    AsyncIteratorProtocol<Element, Failure> { associatedtype Failure: Error = any Error mutating func next( isolation actor: isolated (any Actor)? ) async throws(Failure) -> Element? }
  39. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences ✅ • SE-0314 AsyncStream and

    AsyncThrowingStream ✅ • SE-0388 Convenience Async[Throwing]Stream.makeStream methods ✅ • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol ✅ • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation
  40. αϯϓϧίʔυ var value: Int = 0 { didSet { for

    c in continuations { c.yield(value) } } } var values: some AsyncSequence<Int, Never> { AsyncStream<Int>(bufferingPolicy: .bufferingNewest(1)) { continuation in continuation.yield(value) self.continuations.insert(continuation) continuation.onTermination = { _ in DispatchQueue.main.async { self.continuations.remove(continuation) } } } } private var continuations: Set<AsyncStream<Int>.Continuation> = []
  41. αϯϓϧίʔυ var value: Int = 0 { didSet { for

    c in continuations { c.yield(value) } } } var values: some AsyncSequence<Int, Never> { AsyncStream<Int>(bufferingPolicy: .bufferingNewest(1)) { continuation in continuation.yield(value) self.continuations.insert(continuation) continuation.onTermination = { _ in DispatchQueue.main.async { self.continuations.remove(continuation) } } } } private var continuations: Set<AsyncStream<Int>.Continuation> = [] where Element: Hashable
  42. ContinuationΛͲ͏΍ͬͯHashableʹ͢Δͷ • Continuationͷத਎͸class _StorageͳͷͰ͍ͦͭΛ࢖͏ • static func == (Self, Self)

    -> Bool • _StorageͷಉҰੑΛݟΕ͹OK • func hash(into: inout Hasher) • ObjectIdentifier(storage)ΛࠞͥΕ͹OK https://github.com/swiftlang/swift/blob/8c1cc1b78a7bd4b46d53706e92ab864c25f09f04/stdlib/public/Concurrency/AsyncStream.swift#L478-L492
  43. ΍͍ͬͯͥ͘ʂ • SE-0298 Async/Await: Sequences ✅ • SE-0314 AsyncStream and

    AsyncThrowingStream ✅ • SE-0388 Convenience Async[Throwing]Stream.makeStream methods ✅ • SE-0421 Generalize e ff ect polymorphism for AsyncSequence and AsyncIteratorProtocol ✅ • SE-0468 Hashable conformance for Async(Throwing)Stream.Continuation ✅