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

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

 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 ✅