[swift-evolution] Proposal: Implement == and < for tuples where possible, up to some high arity

Kevin Ballard kevin at sb.org
Mon Dec 7 14:22:19 CST 2015

On Mon, Dec 7, 2015, at 12:01 PM, Dmitri Gribenko wrote:
> On Mon, Dec 7, 2015 at 11:48 AM, Kevin Ballard via swift-evolution <swift-evolution at swift.org> wrote:
>> __
>> I'd really like to see tuples support comparison operators when
>> possible. Eventually they should even conform to the
>> Equatable/Comparable protocols, but that requires tuples being able
>> to conform to protocols at all to begin with.
>> In the absence of some sort of variadic type parameters, we'd only be
>> able to support the comparison operators on tuples up to some
>> predefined arity. There's precedent in Rust and Haskell for this.
>> Rust defines these operations up to arity 12, Haskell defines them up
>> to arity 15.
>> Behavior of == should be obvious. Behavior of the ordered
>> comparison operators would work like comparison of strings, where
>> the first element is compared, and if equal, the second element is
>> compared, etc.
>> This would be implemented using some .gyb code that generates
>> declarations that look something like
>> func == <A: Equatable, B: Equatable, C: Equatable>(lhs: (A, B, C),
>> rhs: (A, B, C)) -> Bool {    return lhs.0 == rhs.0 && lhs.1 == rhs.1
>> && lhs.2 == rhs.2 }
>> func < <A: Comparable, B: Comparable, C: Comparable>(lhs: (A, B, C),
>> rhs: (A, B, C)) -> Bool {    if lhs.0 != rhs.0 { return lhs.0 < rhs.0
>> }    if lhs.1 != rhs.1 { return lhs.1 < rhs.1 }    return lhs.2 <
>> rhs.2 }
>> func > <A: Comparable, B: Comparable, C: Comparable>(lhs: (A, B, C),
>> rhs: (A, B, C)) -> Bool {    if lhs.0 != rhs.0 { return lhs.0 > rhs.0
>> }    if lhs.1 != rhs.1 { return lhs.1 > rhs.1 }    return lhs.2 >
>> rhs.2 }
> Looks like a good idea to me!  Also the <= and >= operators, right?

Yeah, and != too. I just skipped them for brevity.

> What concerns we with massive code generation is the code size of the
> core swift library.  It would be definitely important to see how much
> code this adds, depending on the number of tuple elements.

Good question. What's the best way to measure this? File size of build/$target/swift-macosx-
x86_64/lib/swift/macosx/libswiftCore.dylib (does that even include
generic functions)? Or the x86_64/libswiftCore.dylib from the same
folder (what's the difference)? Or x86_64/Swift.swiftmodule?
Something else?

> I personally don't see a point in going as high as 12 tuple elements.
> About 4 or 5 makes sense to me.  Given that Swift does not have
> variadic generics right now, these long tuples have to be defined by
> someone manually.  If one is defining a tuple that is that long, I'd
> argue that they should be using a custom struct instead.

Depends on how much code size it is. I'd rather err on the side of
defining it for a higher arity tuple than we expect people to actually
use in practice. Just because it's probably a good idea to not point
more than a handful of elements in a tuple doesn't mean people will
actually stick to that, and it's surprising behavior to have ==
suddenly break because you added one more (Equatable) value to the
tuple. As an example, my coworker recently wrote some code that uses a
tuple of 7 elements (as a typedef). It probably should have been a
struct, but I think it was originally defined with just 3 or 4 elements
and sprouted the others as he worked on it. Granted, this particular
tuple wouldn't actually support ==, but I'm sure others have written
similarly long tuples.

I'll probably prototype this some time today, and I can produce some
measurements of code size at different arities (if I can figure out the
best way to measure that).

-Kevin Ballard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151207/7854782c/attachment.html>

More information about the swift-evolution mailing list