Skip to content

Instantly share code, notes, and snippets.

@ollieatkinson
Last active April 22, 2024 15:13
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ollieatkinson/9fb893edbde536f24dec79736285ebdf to your computer and use it in GitHub Desktop.
Save ollieatkinson/9fb893edbde536f24dec79736285ebdf to your computer and use it in GitHub Desktop.
Implementation of `Tuple` type using Swift's new parameter packs
public struct Tuple<each T> {
public private(set) var value: (repeat each T)
public init(_ value: repeat each T) { self.value = (repeat each value) }
}
extension Tuple {
public func map<each U>(
_ transform: (repeat each T) throws -> (repeat each U)
) rethrows -> (repeat each U) {
try (repeat each transform(repeat each value))
}
public func flatMap<each U>(
_ transform: (repeat each T) throws -> Tuple<repeat each U>
) rethrows -> Tuple<repeat each U> {
try transform(repeat each value)
}
public func appending<U>(
_ item: U
) -> Tuple<repeat each T, U> {
Tuple<repeat each T, U>(repeat each value, item)
}
}
extension Tuple: Equatable where repeat each T: Equatable {
public static func == (lhs: Tuple<repeat each T>, rhs: Tuple<repeat each T>) -> Bool {
var result: [Bool] = []
repeat result.append((each lhs.value) == (each rhs.value))
return result.allSatisfy { $0 }
}
}
extension Tuple: Hashable where repeat each T: Hashable {
public func hash(into hasher: inout Hasher) {
repeat (each value).hash(into: &hasher)
}
}
extension Tuple: Comparable where repeat each T: Comparable {
public static func < (lhs: Tuple<repeat each T>, rhs: Tuple<repeat each T>) -> Bool {
var result: [Bool] = []
repeat result.append((each lhs.value) < (each rhs.value))
return result.allSatisfy { $0 }
}
}
extension Tuple: Sendable where repeat each T: Sendable {}
extension Tuple: Decodable where repeat each T: Decodable {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
try self.init(repeat (container.decode((each T).self)))
}
}
extension Tuple: Encodable where repeat each T: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
repeat try container.encode(each value)
}
}
extension Tuple: CustomStringConvertible where repeat each T: CustomStringConvertible {
public var description: String {
var values: [String] = []
repeat values.append((each value).description)
return "\(Self.self)(\(values.joined(separator: ", ")))"
}
}
extension Tuple where repeat each T: OptionalProtocol {
public func get() throws -> Tuple<repeat (each T).Wrapped> {
Tuple<repeat (each T).Wrapped>(try repeat (each value).get())
}
}
@ollieatkinson
Copy link
Author

ollieatkinson commented Feb 21, 2024

OptionalProtocol

protocol OptionalProtocol<Wrapped>: ExpressibleByNilLiteral {
    associatedtype Wrapped
    func get() throws -> Wrapped
}

extension String: Error {}

extension Optional: OptionalProtocol {
    func get() throws -> Wrapped {
        if let self { return self } else { throw "nil" }
    }
}

Map the tuple to a function

let x: Int? = 10
let y: String = "hello"
func foo(i: Int?, s: String) -> Int { 42 }

try Tuple(x, y).map(foo(i:s:))

Unwrap each element in the tuple and map to a function

let x: Int? = 10
let y: String? = "hello"
func foo(i: Int, s: String) -> Int { 42 }

try Tuple(x, y).get().map(foo(i:s:))

@ollieatkinson
Copy link
Author

Thanks to @davedelong for appending(_:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment