Tuples as RawRepresentable


(Haravikk) #1

Following on from discussion about stored properties for enums, I've decided to split off discussion about the possibility of enabling tuples as raw values.

Currently to enable multi-part raw values we need to define a struct that conforms to RawRepresentable; this involves a lot of boilerplate however, and seems like exactly the kind of thing that tuples are ideally suited towards simplifying.

To make tuples automatically conform to RawRepresentable will likely require some compiler magic, but I think it's worth doing, and should be doable with the following additions:

A TupleType protocol (uncertain of correct name for it) to which all specific tuple types will automatically conform, and to which user-defined types may not. This is simply a marker type for now (no methods etc.), as it is essentially just to enable the following:
An ExpressableAsTuple protocol, following the same style as other ExpressableAs* protocols, with the associated type conforming to TupleType, thus requiring that it be a specific tuple definition. All specific tuple types are automatically expressible as themselves.
All tuples will then conform to RawRepresentable, simply returning themselves as their raw value. This may require some magic as well, since I don't know if we want tuples to gain a .rawValue property or not, so could be exposed only when handling them as RawRepresentable specifically?

With ExpressableAsTuple recognised as RawRepresentable, I believe this should satisfy all requirements such that enums, and other types requiring literals, will be able to accept tuples in addition to the types that they currently do.

I think I've covered the requirements here, and I'm hoping someone can confirm if this looks correct. Of course I'm open to any other suggestions on how we might enable tuples as literals, especially if there's an easier way!


(David Sweeris) #2

I'm very much in favor of the functionality, but I don't think the implementation should rely on compiler magic.

- Dave Sweeris

···

On Oct 14, 2016, at 03:24, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

Following on from discussion about stored properties for enums, I've decided to split off discussion about the possibility of enabling tuples as raw values.

Currently to enable multi-part raw values we need to define a struct that conforms to RawRepresentable; this involves a lot of boilerplate however, and seems like exactly the kind of thing that tuples are ideally suited towards simplifying.

To make tuples automatically conform to RawRepresentable will likely require some compiler magic, but I think it's worth doing, and should be doable with the following additions:

A TupleType protocol (uncertain of correct name for it) to which all specific tuple types will automatically conform, and to which user-defined types may not. This is simply a marker type for now (no methods etc.), as it is essentially just to enable the following:
An ExpressableAsTuple protocol, following the same style as other ExpressableAs* protocols, with the associated type conforming to TupleType, thus requiring that it be a specific tuple definition. All specific tuple types are automatically expressible as themselves.
All tuples will then conform to RawRepresentable, simply returning themselves as their raw value. This may require some magic as well, since I don't know if we want tuples to gain a .rawValue property or not, so could be exposed only when handling them as RawRepresentable specifically?

With ExpressableAsTuple recognised as RawRepresentable, I believe this should satisfy all requirements such that enums, and other types requiring literals, will be able to accept tuples in addition to the types that they currently do.

I think I've covered the requirements here, and I'm hoping someone can confirm if this looks correct. Of course I'm open to any other suggestions on how we might enable tuples as literals, especially if there's an easier way!
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #3

Well it's not too much in the way of magic really, more just that we need Swift to see tuples as conforming to RawRepresentable and ExpressableAsTuple, although they currently aren't types in the normal sense. So the protocols being used will be the same as you might use yourself, they'll just be applied automatically for tuples.

It'd be neat if it could be done properly, but that could involve even more work, but doing this automatically for now should be fairly simple (though I say that as a person who wouldn't be the one doing it :wink:

···

On 14 Oct 2016, at 09:49, David Sweeris <davesweeris@mac.com> wrote:

I'm very much in favor of the functionality, but I don't think the implementation should rely on compiler magic.

- Dave Sweeris


(Karl) #4

You can already do this; you just need to implement RawRep manually.

What I think you mean to propose is that the compiler shorthand we have (which synthesises the conformance if you use the equal signs next to the cases) be extended to support tuples of the types it currently supports. That's a relatively simple, non-source-breaking additive change. It likely doesn't fit in the scope of swift 4 phase 1, though (sorry, I've been guilty of chatting about non-abi stuff too as I encounter things which irritate me; trying to be more disciplined)

Karl

···

Sent from my iPad

On 14 Oct 2016, at 12:55, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 14 Oct 2016, at 09:49, David Sweeris <davesweeris@mac.com> wrote:

I'm very much in favor of the functionality, but I don't think the implementation should rely on compiler magic.

- Dave Sweeris

Well it's not too much in the way of magic really, more just that we need Swift to see tuples as conforming to RawRepresentable and ExpressableAsTuple, although they currently aren't types in the normal sense. So the protocols being used will be the same as you might use yourself, they'll just be applied automatically for tuples.

It'd be neat if it could be done properly, but that could involve even more work, but doing this automatically for now should be fairly simple (though I say that as a person who wouldn't be the one doing it :wink:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Karl) #5

Example:

enum something {
    case onething
    case anotherthing
}
extension something : RawRepresentable {
    typealias RawValue = (Int, Int)
    
    init?(rawValue: something.RawValue) {
        switch rawValue {
        case (1, 1):
            self = .onething
        case (2, _):
            self = .anotherthing
        default:
            return nil
        }
    }
    
    var rawValue: (Int, Int) {
        switch self {
        case .onething: return (1, 1)
        case .anotherthing: return (2, 0)
        }
    }
}

let whatisit = something(rawValue: (1, 1))
something.onething.rawValue

Karl

···

Sent from my iPad

On 14 Oct 2016, at 19:04, Karl Wagner <razielim@gmail.com> wrote:

You can already do this; you just need to implement RawRep manually.

What I think you mean to propose is that the compiler shorthand we have (which synthesises the conformance if you use the equal signs next to the cases) be extended to support tuples of the types it currently supports. That's a relatively simple, non-source-breaking additive change. It likely doesn't fit in the scope of swift 4 phase 1, though (sorry, I've been guilty of chatting about non-abi stuff too as I encounter things which irritate me; trying to be more disciplined)

Karl

Sent from my iPad

On 14 Oct 2016, at 12:55, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 14 Oct 2016, at 09:49, David Sweeris <davesweeris@mac.com> wrote:

I'm very much in favor of the functionality, but I don't think the implementation should rely on compiler magic.

- Dave Sweeris

Well it's not too much in the way of magic really, more just that we need Swift to see tuples as conforming to RawRepresentable and ExpressableAsTuple, although they currently aren't types in the normal sense. So the protocols being used will be the same as you might use yourself, they'll just be applied automatically for tuples.

It'd be neat if it could be done properly, but that could involve even more work, but doing this automatically for now should be fairly simple (though I say that as a person who wouldn't be the one doing it :wink:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #6

Huh, see, that's why I posted the thread; I didn't know you could do it that way (I've been trying the RawRepresentable part as its own type).
In that case yes, it seems like all that's need is an expansion of what's allowable on the rhs of raw value enum cases.

···

On 14 Oct 2016, at 18:11, Karl Wagner <razielim@gmail.com> wrote:

Example:

enum something {
    case onething
    case anotherthing
}
extension something : RawRepresentable {
    typealias RawValue = (Int, Int)
    
    init?(rawValue: something.RawValue) {
        switch rawValue {
        case (1, 1):
            self = .onething
        case (2, _):
            self = .anotherthing
        default:
            return nil
        }
    }
    
    var rawValue: (Int, Int) {
        switch self {
        case .onething: return (1, 1)
        case .anotherthing: return (2, 0)
        }
    }
}

let whatisit = something(rawValue: (1, 1))
something.onething.rawValue

Karl

Sent from my iPad

On 14 Oct 2016, at 19:04, Karl Wagner <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

You can already do this; you just need to implement RawRep manually.

What I think you mean to propose is that the compiler shorthand we have (which synthesises the conformance if you use the equal signs next to the cases) be extended to support tuples of the types it currently supports. That's a relatively simple, non-source-breaking additive change. It likely doesn't fit in the scope of swift 4 phase 1, though (sorry, I've been guilty of chatting about non-abi stuff too as I encounter things which irritate me; trying to be more disciplined)

Karl

Sent from my iPad

On 14 Oct 2016, at 12:55, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 14 Oct 2016, at 09:49, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

I'm very much in favor of the functionality, but I don't think the implementation should rely on compiler magic.

- Dave Sweeris

Well it's not too much in the way of magic really, more just that we need Swift to see tuples as conforming to RawRepresentable and ExpressableAsTuple, although they currently aren't types in the normal sense. So the protocols being used will be the same as you might use yourself, they'll just be applied automatically for tuples.

It'd be neat if it could be done properly, but that could involve even more work, but doing this automatically for now should be fairly simple (though I say that as a person who wouldn't be the one doing it :wink:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Karl) #7

Huh, see, that's why I posted the thread; I didn't know you could do it that way (I've been trying the RawRepresentable part as its own type).
In that case yes, it seems like all that's need is an expansion of what's allowable on the rhs of raw value enum cases.

And that’s why I come here - to share the little bits that I’ve learned :slight_smile:

I think a lot of people have misconceptions about what RawRep is, and the inheritance syntax for enums doesn’t much help that. It doesn’t affect the storage or layout of the enum whatsoever; it’s just a protocol conformance. The compiler generates these same kind of switch statements, and that’s really the only reason AFAIK that we have the limitations (e.g. int/string literal) that we do.

There are no restrictions on what can be RawRepresentable (structs and classes can also conform), and no limitation on the type of RawType (can also be a struct or a class). You just need to implement it yourself in those cases; I’m guessing because there are complex edge-cases which we don’t want hidden away in a location you can’t easily debug.

Tuples of Ints and Strings, however, seem like they could easily be supported. For example, we could check that there are no overlapping cases.

- Karl

···

On 14 Oct 2016, at 19:56, Haravikk <swift-evolution@haravikk.me> wrote:

On 14 Oct 2016, at 18:11, Karl Wagner <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

Example:

enum something {
    case onething
    case anotherthing
}
extension something : RawRepresentable {
    typealias RawValue = (Int, Int)
    
    init?(rawValue: something.RawValue) {
        switch rawValue {
        case (1, 1):
            self = .onething
        case (2, _):
            self = .anotherthing
        default:
            return nil
        }
    }
    
    var rawValue: (Int, Int) {
        switch self {
        case .onething: return (1, 1)
        case .anotherthing: return (2, 0)
        }
    }
}

let whatisit = something(rawValue: (1, 1))
something.onething.rawValue

Karl

Sent from my iPad

On 14 Oct 2016, at 19:04, Karl Wagner <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

You can already do this; you just need to implement RawRep manually.

What I think you mean to propose is that the compiler shorthand we have (which synthesises the conformance if you use the equal signs next to the cases) be extended to support tuples of the types it currently supports. That's a relatively simple, non-source-breaking additive change. It likely doesn't fit in the scope of swift 4 phase 1, though (sorry, I've been guilty of chatting about non-abi stuff too as I encounter things which irritate me; trying to be more disciplined)

Karl

Sent from my iPad

On 14 Oct 2016, at 12:55, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 14 Oct 2016, at 09:49, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

I'm very much in favor of the functionality, but I don't think the implementation should rely on compiler magic.

- Dave Sweeris

Well it's not too much in the way of magic really, more just that we need Swift to see tuples as conforming to RawRepresentable and ExpressableAsTuple, although they currently aren't types in the normal sense. So the protocols being used will be the same as you might use yourself, they'll just be applied automatically for tuples.

It'd be neat if it could be done properly, but that could involve even more work, but doing this automatically for now should be fairly simple (though I say that as a person who wouldn't be the one doing it :wink:
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #8

Does the type of the tuples really matter? For equality it should be sufficient just to compare them directly as bytes; since they will be of the same tuple type this should either result in equality or not without too much complexity, otherwise we'd need to require the types are Equatable or Hashable but that seems a bit like overkill.

I've started a preliminary proposal for tuples as enum raw value types; it's pretty straightforward so far as I'm not sure what more detail is really needed, except perhaps for this equality issue:
https://github.com/Haravikk/swift-evolution/blob/master/proposals/NNNN-allow-tuples-as-enum-raw-values.md

···

On 14 Oct 2016, at 19:11, Karl <razielim@gmail.com> wrote:

On 14 Oct 2016, at 19:56, Haravikk <swift-evolution@haravikk.me <mailto:swift-evolution@haravikk.me>> wrote:

Huh, see, that's why I posted the thread; I didn't know you could do it that way (I've been trying the RawRepresentable part as its own type).
In that case yes, it seems like all that's need is an expansion of what's allowable on the rhs of raw value enum cases.

And that’s why I come here - to share the little bits that I’ve learned :slight_smile:

I think a lot of people have misconceptions about what RawRep is, and the inheritance syntax for enums doesn’t much help that. It doesn’t affect the storage or layout of the enum whatsoever; it’s just a protocol conformance. The compiler generates these same kind of switch statements, and that’s really the only reason AFAIK that we have the limitations (e.g. int/string literal) that we do.

There are no restrictions on what can be RawRepresentable (structs and classes can also conform), and no limitation on the type of RawType (can also be a struct or a class). You just need to implement it yourself in those cases; I’m guessing because there are complex edge-cases which we don’t want hidden away in a location you can’t easily debug.

Tuples of Ints and Strings, however, seem like they could easily be supported. For example, we could check that there are no overlapping cases.


(Xiaodi Wu) #9

Yes it absolutely matters what the types are. Two floating point values can
compare equal when their raw bytes differ and they can compare not equal
even when their raw bytes are the same, and it would be absolutely
necessary that a tuple of two floating point values behaves the same way.

Moreover, if a value is not equatable, it's nonsense to ask if tuples of
two of them are equal. Otherwise, you've effectively forced every value
type to be equatable, since it'd be ridiculous if (a, a) == (b, b) didn't
imply a == b.

···

On Sat, Oct 15, 2016 at 19:44 Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

On 14 Oct 2016, at 19:11, Karl <razielim@gmail.com> wrote:

On 14 Oct 2016, at 19:56, Haravikk <swift-evolution@haravikk.me> wrote:

Huh, see, that's why I posted the thread; I didn't know you could do it
that way (I've been trying the RawRepresentable part as its own type).
In that case yes, it seems like all that's need is an expansion of what's
allowable on the rhs of raw value enum cases.

And that’s why I come here - to share the little bits that I’ve learned :slight_smile:

I think a lot of people have misconceptions about what RawRep is, and the
inheritance syntax for enums doesn’t much help that. It doesn’t affect the
storage or layout of the enum whatsoever; it’s just a protocol conformance.
The compiler generates these same kind of switch statements, and that’s
really the only reason AFAIK that we have the limitations (e.g. int/string
literal) that we do.

There are no restrictions on what can be RawRepresentable (structs and
classes can also conform), and no limitation on the type of RawType (can
also be a struct or a class). You just need to implement it yourself in
those cases; I’m guessing because there are complex edge-cases which we
don’t want hidden away in a location you can’t easily debug.

Tuples of Ints and Strings, however, seem like they could easily be
supported. For example, we could check that there are no overlapping cases.

Does the type of the tuples really matter? For equality it should be
sufficient just to compare them directly as bytes; since they will be of
the same tuple type this should either result in equality or not without
too much complexity, otherwise we'd need to require the types are Equatable
or Hashable but that seems a bit like overkill.

I've started a preliminary proposal for tuples as enum raw value types;
it's pretty straightforward so far as I'm not sure what more detail is
really needed, except perhaps for this equality issue:

https://github.com/Haravikk/swift-evolution/blob/master/proposals/NNNN-allow-tuples-as-enum-raw-values.md
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #10

All I meant really is that you can always compare equality at the memory level, regardless of Equatable conformance; the type checker ensures the tuples being compared can only contain the same types in the same order, at which point a bitwise memory comparison can determine they are equal in the strictest possible sense, much like comparing whether two object references point to the same object (you're comparing the pointers).

But actually it doesn't seem to even matter; tuples are already Equatable if all of their components are (again, something I don't seem to actually use), so that should be more than sufficient for using them as enum raw values, we can just ignore tuples that aren't/require the developer to add Equatable to any components that aren't.

···

On 15 Oct 2016, at 16:04, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Yes it absolutely matters what the types are. Two floating point values can compare equal when their raw bytes differ and they can compare not equal even when their raw bytes are the same, and it would be absolutely necessary that a tuple of two floating point values behaves the same way.

Moreover, if a value is not equatable, it's nonsense to ask if tuples of two of them are equal. Otherwise, you've effectively forced every value type to be equatable, since it'd be ridiculous if (a, a) == (b, b) didn't imply a == b.


#11

Tuples cannot conform to protocols, so despite the existence of an “==”
operator for certain tuples, no tuple conforms to Equatable.

This is problematic, because it means that a function which takes a generic
Equatable parameter cannot be called with a tuple argument, even though an
applicable “==” operator exists.

(Ditto for “Comparable”, *mutatis mutandis*.)

Nevin

···

On Sat, Oct 15, 2016 at 12:28 PM, Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

> On 15 Oct 2016, at 16:04, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
>
> Yes it absolutely matters what the types are. Two floating point values
can compare equal when their raw bytes differ and they can compare not
equal even when their raw bytes are the same, and it would be absolutely
necessary that a tuple of two floating point values behaves the same way.
>
> Moreover, if a value is not equatable, it's nonsense to ask if tuples of
two of them are equal. Otherwise, you've effectively forced every value
type to be equatable, since it'd be ridiculous if (a, a) == (b, b) didn't
imply a == b.

All I meant really is that you can always compare equality at the memory
level, regardless of Equatable conformance; the type checker ensures the
tuples being compared can only contain the same types in the same order, at
which point a bitwise memory comparison can determine they are equal in the
strictest possible sense, much like comparing whether two object references
point to the same object (you're comparing the pointers).

But actually it doesn't seem to even matter; tuples are already Equatable
if all of their components are (again, something I don't seem to actually
use), so that should be more than sufficient for using them as enum raw
values, we can just ignore tuples that aren't/require the developer to add
Equatable to any components that aren't.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Saagar Jha) #12

If you're looking for a use case for tuple equality, I often pack a bunch
of values in a tuple and check it with another, which makes it easy to
compare a multiple values at once and perform something only if all of them
are equal.

···

On Sat, Oct 15, 2016 at 09:28 Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

> On 15 Oct 2016, at 16:04, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
>
> Yes it absolutely matters what the types are. Two floating point values
can compare equal when their raw bytes differ and they can compare not
equal even when their raw bytes are the same, and it would be absolutely
necessary that a tuple of two floating point values behaves the same way.
>
> Moreover, if a value is not equatable, it's nonsense to ask if tuples of
two of them are equal. Otherwise, you've effectively forced every value
type to be equatable, since it'd be ridiculous if (a, a) == (b, b) didn't
imply a == b.

All I meant really is that you can always compare equality at the memory
level, regardless of Equatable conformance; the type checker ensures the
tuples being compared can only contain the same types in the same order, at
which point a bitwise memory comparison can determine they are equal in the
strictest possible sense, much like comparing whether two object references
point to the same object (you're comparing the pointers).

But actually it doesn't seem to even matter; tuples are already Equatable
if all of their components are (again, something I don't seem to actually
use), so that should be more than sufficient for using them as enum raw
values, we can just ignore tuples that aren't/require the developer to add
Equatable to any components that aren't.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Haravikk) #13

Yeah, since the operators are implemented though perhaps some kind of magic can be used? It seems strange that the following is valid:

  struct Foo : Equatable { let value:(Int, Int) }
  func == (lhs:Foo, rhs:Foo) -> Bool { return lhs.value == rhs.value }

Yet tuples can't just be Equatable etc. But I'm wondering whether that falls into separate issue territory, such that it should be done first as its own proposal?

···

On 15 Oct 2016, at 18:21, Nevin Brackett-Rozinsky <nevin.brackettrozinsky@gmail.com> wrote:

Tuples cannot conform to protocols, so despite the existence of an “==” operator for certain tuples, no tuple conforms to Equatable.

This is problematic, because it means that a function which takes a generic Equatable parameter cannot be called with a tuple argument, even though an applicable “==” operator exists.

(Ditto for “Comparable”, mutatis mutandis.)

Nevin


(Karl) #14

Tuples cannot conform to protocols, so despite the existence of an “==” operator for certain tuples, no tuple conforms to Equatable.

This is problematic, because it means that a function which takes a generic Equatable parameter cannot be called with a tuple argument, even though an applicable “==” operator exists.

(Ditto for “Comparable”, mutatis mutandis.)

Nevin

Yeah, since the operators are implemented though perhaps some kind of magic can be used? It seems strange that the following is valid:

  struct Foo : Equatable { let value:(Int, Int) }
  func == (lhs:Foo, rhs:Foo) -> Bool { return lhs.value == rhs.value }

Yet tuples can't just be Equatable etc. But I'm wondering whether that falls into separate issue territory, such that it should be done first as its own proposal?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Tuples are non-nominal (named) types, and that’s why they can’t conform to protocols. There is something in the generics manifesto about possibly allowing them to do that in the future, though:

https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#extensions-of-structural-types

Extensions of structural types

Currently, only nominal types (classes, structs, enums, protocols) can be extended. One could imagine extending structural types—particularly tuple types—to allow them to, e.g., conform to protocols. For example, pulling together variadic generics, parameterized extensions, and conditional conformances, one could express "a tuple type is Equatable if all of its element types are Equatable":

extension<...Elements : Equatable> (Elements...) : Equatable { // extending the tuple type "(Elements...)" to be Equatable
}

- Karl

···

On 16 Oct 2016, at 00:33, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

On 15 Oct 2016, at 18:21, Nevin Brackett-Rozinsky <nevin.brackettrozinsky@gmail.com <mailto:nevin.brackettrozinsky@gmail.com>> wrote:


(Haravikk) #15

Yeah, but that's much further reaching overall; I'm wondering whether it's okay to just call tuples of Equatable types Equatable for the purposes of getting them as enum raw values? I'll maybe put some discussion of timing and other issues into the proposal for this, to keep it open ended.

···

On 16 Oct 2016, at 11:55, Karl <razielim@gmail.com> wrote:

On 16 Oct 2016, at 00:33, Haravikk via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 15 Oct 2016, at 18:21, Nevin Brackett-Rozinsky <nevin.brackettrozinsky@gmail.com <mailto:nevin.brackettrozinsky@gmail.com>> wrote:

Tuples cannot conform to protocols, so despite the existence of an “==” operator for certain tuples, no tuple conforms to Equatable.

This is problematic, because it means that a function which takes a generic Equatable parameter cannot be called with a tuple argument, even though an applicable “==” operator exists.

(Ditto for “Comparable”, mutatis mutandis.)

Nevin

Yeah, since the operators are implemented though perhaps some kind of magic can be used? It seems strange that the following is valid:

  struct Foo : Equatable { let value:(Int, Int) }
  func == (lhs:Foo, rhs:Foo) -> Bool { return lhs.value == rhs.value }

Yet tuples can't just be Equatable etc. But I'm wondering whether that falls into separate issue territory, such that it should be done first as its own proposal?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Tuples are non-nominal (named) types, and that’s why they can’t conform to protocols. There is something in the generics manifesto about possibly allowing them to do that in the future, though:

https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#extensions-of-structural-types

Extensions of structural types

Currently, only nominal types (classes, structs, enums, protocols) can be extended. One could imagine extending structural types—particularly tuple types—to allow them to, e.g., conform to protocols. For example, pulling together variadic generics, parameterized extensions, and conditional conformances, one could express "a tuple type is Equatable if all of its element types are Equatable":

extension<...Elements : Equatable> (Elements...) : Equatable { // extending the tuple type "(Elements...)" to be Equatable
}

- Karl


(Xiaodi Wu) #16

It may be farther reaching, but it's quite salient. Completing genetics is
a Swift 4 focus, and protocol conformance and extensions of structural
types may well have ABI implications, which would make it a phase 1
priority.

Recall that equality for tuples of Equatables is only defined up to an
arity of 6, and that it was implemented in that way as a stopgap. With a
plausible definitive solution in scope for Swift 4, it seems less than
ideal to propose entrenching the stopgap measure by making it even more
elaborate.

···

On Sun, Oct 16, 2016 at 19:47 Haravikk via swift-evolution < swift-evolution@swift.org> wrote:

On 16 Oct 2016, at 11:55, Karl <razielim@gmail.com> wrote:

On 16 Oct 2016, at 00:33, Haravikk via swift-evolution < > swift-evolution@swift.org> wrote:

On 15 Oct 2016, at 18:21, Nevin Brackett-Rozinsky < > nevin.brackettrozinsky@gmail.com> wrote:

Tuples cannot conform to protocols, so despite the existence of an “==”
operator for certain tuples, no tuple conforms to Equatable.

This is problematic, because it means that a function which takes a
generic Equatable parameter cannot be called with a tuple argument, even
though an applicable “==” operator exists.

(Ditto for “Comparable”, *mutatis mutandis*.)

Nevin

Yeah, since the operators are implemented though perhaps some kind of
magic can be used? It seems strange that the following is valid:

struct Foo : Equatable { let value:(Int, Int) }
func == (lhs:Foo, rhs:Foo) -> Bool { return lhs.value == rhs.value }

Yet tuples can't just be Equatable etc. But I'm wondering whether that
falls into separate issue territory, such that it should be done first as
its own proposal?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Tuples are non-nominal (named) types, and that’s why they can’t conform to
protocols. There is something in the generics manifesto about possibly
allowing them to do that in the future, though:

https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#extensions-of-structural-types

Extensions of structural types

Currently, only nominal types (classes, structs, enums, protocols) can be
extended. One could imagine extending structural types—particularly tuple
types—to allow them to, e.g., conform to protocols. For example, pulling
together variadic generics, parameterized extensions, and conditional
conformances, one could express "a tuple type is Equatable if all of its
element types are Equatable":

extension<...Elements : Equatable> (Elements...) : Equatable { // extending the tuple type "(Elements...)" to be Equatable
}

- Karl

Yeah, but that's much further reaching overall; I'm wondering whether it's
okay to just call tuples of Equatable types Equatable for the purposes of
getting them as enum raw values? I'll maybe put some discussion of timing
and other issues into the proposal for this, to keep it open ended.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution