Added the repeater feature we wanted for so long.
This commit is contained in:
parent
49abbea360
commit
64705e7bb7
|
@ -13,8 +13,16 @@ let package = Package(
|
||||||
.library(name: "Beton", targets: ["Beton"]),
|
.library(name: "Beton", targets: ["Beton"]),
|
||||||
.library(name: "XCTBeton", targets: ["XCTBeton"]),
|
.library(name: "XCTBeton", targets: ["XCTBeton"]),
|
||||||
],
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(url: "https://github.com/apple/swift-async-algorithms.git", from: "0.1.0"),
|
||||||
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(name: "Beton"),
|
.target(
|
||||||
|
name: "Beton",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "AsyncAlgorithms", package: "swift-async-algorithms"),
|
||||||
|
]
|
||||||
|
),
|
||||||
.target(
|
.target(
|
||||||
name: "XCTBeton",
|
name: "XCTBeton",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
import Foundation
|
||||||
|
import AsyncAlgorithms
|
||||||
|
|
||||||
|
// MARK: Mappers
|
||||||
|
|
||||||
|
/// Runs the provided callback consecutively one after another,
|
||||||
|
/// passing the current iteration count as an argument,
|
||||||
|
/// and returning the array of results in iteration order.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: Number of times to run the given function.
|
||||||
|
/// - function: The callback to execute mapping its results to the final result.
|
||||||
|
/// - Returns: An array of all the values returned by the callback.
|
||||||
|
public func repeating<T>(count: Int, _ function: (Int) -> T) -> [T] {
|
||||||
|
(0..<count).map { function($0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public typealias AsyncRepeatingChannel<T: Sendable> = AsyncChannel<(iteration: Int, result: T)> where T: Sendable
|
||||||
|
/// Runs the provided callback asynchronously,
|
||||||
|
/// passing the current iteration count as an argument,
|
||||||
|
/// and returning an AsyncSequence of the results.
|
||||||
|
/// **This function is by design out-of-order.**
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: Number of times to run the given function.
|
||||||
|
/// - function: The callback to execute, mapping results to the final result.
|
||||||
|
/// - Returns: A channel of results.
|
||||||
|
public func repeating<T>(
|
||||||
|
count: Int,
|
||||||
|
_ function: @escaping (Int) async -> T
|
||||||
|
) async -> AsyncRepeatingChannel<T> where T: Sendable {
|
||||||
|
let channel = AsyncRepeatingChannel<T>()
|
||||||
|
|
||||||
|
Task {
|
||||||
|
await withTaskGroup(of: Void.self) { group in
|
||||||
|
for i in 0..<count {
|
||||||
|
group.addTask { await channel.send((i, function(i))) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
channel.finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
return channel
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Resolvers
|
||||||
|
|
||||||
|
/// Runs the provided callback consecutively one after another, returning the array of results in iteration order.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: Number of times to run the given function.
|
||||||
|
/// - function: The callback to execute mapping its results to the final result.
|
||||||
|
/// - Returns: An array of all the values returned by the callback.
|
||||||
|
public func repeating<T>(
|
||||||
|
count: Int,
|
||||||
|
_ function: @autoclosure () -> T
|
||||||
|
) -> [T] {
|
||||||
|
repeating(count: count) { _ in function() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs the provided callback asynchronously, returning the results.
|
||||||
|
/// **This function is by design out-of-order.**
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: Number of times to run the given function.
|
||||||
|
/// - function: The callback to execute mapping its results to the final result.
|
||||||
|
/// - Returns: A channel of all the values returned by the callback.
|
||||||
|
public func repeating<T>(
|
||||||
|
count: Int,
|
||||||
|
_ function: @escaping @autoclosure () async -> T
|
||||||
|
) async -> AsyncRepeatingChannel<T> where T: Sendable {
|
||||||
|
await repeating(count: count) { _ in await function()}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Performers
|
||||||
|
|
||||||
|
/// Runs the provided callback `count` number of times, ignoring its results.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: Number of times to run the given function.
|
||||||
|
/// - function: The callback to execute `count` times.
|
||||||
|
public func repeating(count: Int, _ function: @autoclosure () -> ()) {
|
||||||
|
let _ = repeating(count: count) { [function] _ in function() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs asynchronously the provided callback `count` number of times, ignoring the results.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - count: Number of times to run the given function.
|
||||||
|
/// - function: The callback to execute `count` times
|
||||||
|
public func repeating(
|
||||||
|
count: Int,
|
||||||
|
_ function: @autoclosure @escaping () async -> ()
|
||||||
|
) async {
|
||||||
|
let _ = await repeating(count: count) { _ in await function() }
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ class BundleTest: XCTestCase {
|
||||||
override func tearDown() {
|
override func tearDown() {
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
XCTAssertMetric(.cpu, .cycles, .average(maximum: 5000))
|
XCTAssertMetric(.cpu, .cycles, .average(maximum: 5000))
|
||||||
XCTAssertMetric(.cpu, .instructionsRetired, .average(maximum: 4500))
|
XCTAssertMetric(.cpu, .instructionsRetired, .average(maximum: 10_000))
|
||||||
XCTAssertMetric(.cpu, .time, .average(maximum: 0.002))
|
XCTAssertMetric(.cpu, .time, .average(maximum: 0.002))
|
||||||
XCTAssertMetric(.memory, .physical, .average(maximum: 60))
|
XCTAssertMetric(.memory, .physical, .average(maximum: 60))
|
||||||
XCTAssertMetric(.memory, .physicalPeak, .average(maximum: 0))
|
XCTAssertMetric(.memory, .physicalPeak, .average(maximum: 0))
|
||||||
|
@ -15,25 +15,25 @@ class BundleTest: XCTestCase {
|
||||||
|
|
||||||
func testLocalizationBundles() {
|
func testLocalizationBundles() {
|
||||||
measure(metrics: .defaults) {
|
measure(metrics: .defaults) {
|
||||||
Bundle.module.localizationBundles
|
let _ = Bundle.module.localizationBundles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLocalizedString_keyOnly() {
|
func testLocalizedString_keyOnly() {
|
||||||
measure(metrics: .defaults) {
|
measure(metrics: .defaults) {
|
||||||
Bundle.module.localizedString("Test")
|
let _ = Bundle.module.localizedString("Test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLocalizedString_keyAndTableOnly() {
|
func testLocalizedString_keyAndTableOnly() {
|
||||||
measure(metrics: .defaults) {
|
measure(metrics: .defaults) {
|
||||||
Bundle.module.localizedString("Test", from: "Test")
|
let _ = Bundle.module.localizedString("Test", from: "Test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testLocalizedString_keyAndValueOnly() {
|
func testLocalizedString_keyAndValueOnly() {
|
||||||
measure(metrics: .defaults) {
|
measure(metrics: .defaults) {
|
||||||
Bundle.module.localizedString("Test", fallback: "Test")
|
let _ = Bundle.module.localizedString("Test", fallback: "Test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
@testable import Beton
|
||||||
|
import XCTBeton
|
||||||
|
|
||||||
|
class RepeatingTests: XCTestCase {
|
||||||
|
func testRepeating_sync_mapper () {
|
||||||
|
XCTAssertEqual(repeating(count: 3) { $0 + 5 }, [5, 6, 7])
|
||||||
|
XCTAssertEqual(repeating(count: 3) { $0 + 10 }, [10, 11, 12])
|
||||||
|
XCTAssertEqual(repeating(count: 5) { $0 + 5 }, [5, 6, 7, 8, 9])
|
||||||
|
XCTAssertEqual(repeating(count: 5) { $0 + 10 }, [10, 11, 12, 13, 14])
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepeating_sync_resolver () {
|
||||||
|
XCTAssertEqual(repeating(count: 3, 5), [5, 5, 5,])
|
||||||
|
XCTAssertEqual(repeating(count: 3, 10), [10, 10, 10])
|
||||||
|
XCTAssertEqual(repeating(count: 5, 5), [5, 5, 5, 5, 5,])
|
||||||
|
XCTAssertEqual(repeating(count: 5, 10), [10, 10, 10, 10, 10])
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepeating_sync_performer() {
|
||||||
|
var counter = 0
|
||||||
|
|
||||||
|
repeating(count: 3, counter += 1)
|
||||||
|
XCTAssertEqual(counter, 3)
|
||||||
|
|
||||||
|
repeating(count: 5, counter += 2)
|
||||||
|
XCTAssertEqual(counter, 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepeating_async_mapper() async throws {
|
||||||
|
for try await item in await repeating(count: 10, { $0 + 5 }) {
|
||||||
|
XCTAssertEqual(item.result, item.iteration + 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepeating_async_resolver() async throws {
|
||||||
|
for try await item in await repeating(count: 10, 100) {
|
||||||
|
XCTAssertEqual(item.result, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRepeating_async_performer() async throws {
|
||||||
|
var a = [Int]()
|
||||||
|
await repeating(count: 13, a.append(1))
|
||||||
|
print(a)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue