Small package to work around "tuples cannot conform to protocol"

I made an extremely tiny package to conform tuples to protocols using parameter packs. I made this because I've been needing Hashable, Comparable and Codable tuples. Here’s a copy of the README for posterity:

Swift Tuple

An extremely simple solution to conform tuples to protocols.

Overview

Did you ever want to conform Swift tuples to protocols?

Now you can!

extension Tuple where repeat each T: MyProtocol {
    func myProtocolRequirement() {
        // ...
    }
}

extension Int: MyProtocol { /* ... */ }
extension String: MyProtocol { /* ... */ }
extension Bool: MyProtocol { /* ... */ }

let test = Tuple(1, "String", false)
test.myProtocolRequirement() // works! :)
test == Tuple(flatten: (1, "String", false)) // true
try JSONEncodable().encode(test) // [1, "String", false]
Tuple(1, 2) < Tuple(0, 560) // false
Set([Tuple(0, "Hello"), Tuple(1, "World!")])

Tuple conditionally conforms to a number of protocols for your convenience, such as Equatable, Hashable, Comparable and Codable.

3 Likes

You got to have unit tests. Your == logic is backwards for example.

4 Likes

Excellent point, I hadn’t noticed because the project in which I use this also had its logic backwards. That’s embarrassing.

Oh I know why that happened, I used to have an Array as backing storage before parameter packs:

for (lhs, rhs) in zip(lhs, rhs) where lhs != rhs {
    return false
}
return true

Parameter packs don't support where clauses in for-loops however (reason unclear) and I moved it to an if, then when copied to the package I changed it for a guard forgetting to invert the condition.

Unit tests it is!

2 Likes

That's quite cool, thank you!

It's not quite a tuple, but, If we had something like this in the language (standard library) would we need to have anything else. Bonus point - compared to normal tuples this tuple could be of arity 1 (and even 0).

PS. (init(flatten:) doesn't sound right. maybe init(tuple:) or init(rawValue:) or init(rawTuple:).

2 Likes

This kind of functionality directly on regular tuples were pitched and accepted so it’ll happen eventually!

In the meantime this is my workaround!

1 Like

Good to know.

BTW, could I simulate InlineArray with this approach? If not – what's missing? If yes – why do we need InlineArray?

No, for the same reasons you couldn’t replace it with regular tuples. Or you could, but it was a pain and only applicable in certain cases.

For example, I built emulator which would’ve needed a 2MB-sized tuple to replace InlineArray, which would’ve crashed the compiler.

I recommend reading the discussion thread on InlineArray, there’s answers that are much more in depth!

Hi, this does sound interesting but this post should really be in Community Showcase not in Using Swift

2 Likes