import Foundation

/// A set of extensions to the Sequence protocl to make the asynchronous programming easier.
extension Sequence {
	func asyncMap<T>(_ transform: @escaping (Element) async -> T) async -> [T] {
		await withTaskGroup(of: T.self) { group in
			var transformedElements = [T]()

			for element in self {
				group.addTask {
					await transform(element)
				}
			}

			for await transformedElement in group {
				transformedElements.append(transformedElement)
			}

			return transformedElements
		}
	}

	func asyncThrowingMap<T>(_ transform: @escaping (Element) async throws -> T) async throws -> [T] {
		try await withThrowingTaskGroup(of: T.self) { group in
			var transformedElements = [T]()
			for element in self {
				group.addTask {
					try await transform(element)
				}
			}
			for try await transformedElement in group {
				transformedElements.append(transformedElement)
			}
			return transformedElements
		}
	}
}
