Welcome to CollectionConcurrencyKit, a lightweight Swift package that adds asynchronous and concurrent versions of the standard map
, flatMap
, compactMap
, and forEach
APIs to all Swift collections that conform to the Sequence
protocol. That includes built-in types, like Array
, Set
, and Dictionary
, as well as any custom collections that conform to that protocol.
CollectionConcurrencyKit can be used to implement high-performance data processing and algorithms in a way that fully utilizes Swift's built-in concurrency system. It's heavily unit tested, fully documented, and used in production to generate swiftbysundell.com.
The following changes have been made to this fork of CollectionConcurrencyKit:
@inlinable
to allow the Swift compiler to inline the provided functions in performance-critical situations.Sources
folder to Sources/CollectionConcurrencyKit
and Tests
folder to Tests/CollectionConcurrencyKit
.The async variants of CollectionConcurrencyKit's APIs enable you to call async
-marked functions within your various mapping and forEach
iterations.
Note: Unlike the original package, this version does not maintain the original order at this time. The author is currently considering whether to modify the code and include the ability to preserve order.
For example, here's how we could use asyncMap
to download a series of HTML strings from a collection of URLs:
let urls = [
URL(string: "https://apple.com")!,
URL(string: "https://swift.org")!,
URL(string: "https://swiftbysundell.com")!
]
let htmlStrings = try await urls.asyncMap { url -> String in
let (data, _) = try await URLSession.shared.data(from: url)
return String(decoding: data, as: UTF8.self)
}
And here's how we could use asyncCompactMap
to ignore any download that failed, by returning an optional value, rather than throwing an error:
let htmlStrings = await urls.asyncCompactMap { url -> String? in
do {
let (data, _) = try await URLSession.shared.data(from: url)
return String(decoding: data, as: UTF8.self)
} catch {
return nil
}
}
Each of CollectionConcurrencyKit's APIs come in both throwing and non-throwing variants, so since the above call to asyncCompactMap
doesn't throw, we don't need to use try
when calling it.
CollectionConcurrencyKit also includes concurrent versions of forEach
, map
, flatMap
, and compactMap
, which perform their iterations in parallel.
For example, since our above HTML downloading code consists of completely separate operations, we could instead use concurrentMap
to perform each of those operations in parallel for a significant speed boost:
let htmlStrings = try await urls.concurrentMap { url -> String in
let (data, _) = try await URLSession.shared.data(from: url)
return String(decoding: data, as: UTF8.self)
}
And if we instead wanted to parallelize our asyncCompactMap
-based variant of the above code, then we could do so by using concurrentCompactMap
:
let htmlStrings = await urls.concurrentCompactMap { url -> String? in
do {
let (data, _) = try await URLSession.shared.data(from: url)
return String(decoding: data, as: UTF8.self)
} catch {
return nil
}
}
CollectionConcurrencyKit adds the following APIs to all Sequence
-conforming Swift collections:
asyncForEach
asyncMap
asyncCompactMap
asyncFlatMap
concurrentForEach
concurrentMap
concurrentCompactMap
concurrentFlatMap
Both throwing and non-throwing versions of all the above APIs are included. To learn more about map
, flatMap
, and compactMap
in general, check out this article.
CollectionConcurrencyKit works on all 2021 releases of Apple operating systems (iOS 15, macOS 12, watchOS 8, and tvOS 15).
CollectionConcurrencyKit is distributed using the Swift Package Manager. To install it within another Swift package, add it as a dependency within your Package.swift
manifest:
let package = Package(
// ...
dependencies: [
.package(url: "https://github.com/nhubbard/CollectionConcurrencyKit.git", from: "2.0.0")
],
// ...
)
To add this package from Xcode, go to File > Add Packages...
and paste the repository URL into the search bar to add it to your project.
Then, import it wherever you'd like to use it:
import CollectionConcurrencyKit
For more information on how to use the Swift Package Manager, check out this article, or the official documention.
This fork of CollectionConcurrencyKit, like the original package, is made freely available to the entire Swift community under the very permissive MIT license.
However, this doesn't come with any support guarantees. You may open an issue in GitHub Issues, but there is no guarantee that the author will respond to it.
Before you start using CollectionConcurrencyKit, it is highly recommended that you spend some time familiarizing yourself with the implementation, in case you run into any issues that you'll need to debug.
If you've found a bug, documentation typo, or want to add an improvement to the code itself (such as a performance improvement or new functions), then feel free to fork the repository, make your contributions, and then open a pull request to contribute it back to this repository.
If you add a new feature or improve performance, please include corresponding new unit tests (for new features) or ensure that the existing unit tests still pass after your changes are applied.
This library is considered mostly feature-complete, however I'm open to entertaining additional features or improvements if you see an opportunity to make them.
Significant thanks are in order to @JohnSundell, who originally authored this library, along with @Frizlab and @AndrewBarba, who respectively created and reviewed the task groups implementation of the concurrency functions.
link |
Stars: 0 |
Last commit: 33 weeks ago |
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics