# Redeclaration of named tuple members

**URL:** <https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756>\
**Category:** Using Swift\
**Tags:** tuple\
**Created:** [December 12, 2018, 8:57am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756 "2018-12-12T08:57:15Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 8:57am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/1 "2018-12-12T08:57:15Z")

</div>

The following code does not compile (Xcode 10.1 default toolchain and Swift 5 Snapshot 2018-12-04 toolchain).

```swift
let counter = 119
let final: (min: Int, sec: Int) = counter.quotientAndRemainder(dividingBy: 60)

```

This gives:

```swift
error: cannot convert value of type '(quotient: Int, remainder: Int)' to specified type '(min: Int, sec: Int)'

```

However, this rather clumsy workaround does exactly this:

```swift
let counter = 119
let foo = counter.quotientAndRemainder(dividingBy: 60)
let bar: (Int, Int) = foo
let final: (min: Int, sec: Int) = bar

print(final) // (min: 1, sec: 59)

```

Couldn't/ shouldn't the type annotated first version work? This is not tuple shuffle, currently in discussion, but perhaps somehow related. Don't know…  
Just had a case in my code where this could have made it better understandable at first glance.

Edit:  
Just getting my head around the tuple shuffle topic.

```swift
var a = (a: 1, b: 2)
print(a) // (a: 1, b: 2)
var b: (b: Int, a: Int) = a
print(b) // (b: 2, a: 1)

```

This shuffles around the elements of the tuple according to their matching names. I would propose that the order of the elements always stays the same, but the names can freely be changed as long as the types match in the original order.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [December 12, 2018, 9:14am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/2 "2018-12-12T09:14:03Z")

</div>

I think this expected because the types are not matched: `(a: Int, b: Int) != (x: Int, y: Int)`

I can‘t test at the moment, can you try putting `as (Int, Int)` at the end of your first example and see if it compiles?!

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 9:21am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/3 "2018-12-12T09:21:07Z")

</div>

Mmhhh… Yes,

```swift
let counter = 119
let foo: (Int, Int) = counter.quotientAndRemainder(dividingBy: 60)
let final: (min: Int, sec: Int) = foo
print(final) // (min: 1, sec: 59)

```

works, but there is still this intermediate step, which I think could/ should be unnecessary.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [December 12, 2018, 9:25am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/4 "2018-12-12T09:25:08Z")

</div>

Again, I can‘t test it right now because I‘m on my phone. I meant something like this, but I‘m not sure if it will compile.

```swift
let final: (min: Int, sec: Int) = counter.quotientAndRemainder(dividingBy: 60) as (Int, Int)

```

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 9:59am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/5 "2018-12-12T09:59:10Z")

</div>

Ah, I see. This actually works (in one line). Clever. Thank you. Nice Idea.^^ However, it still has this explicit name erasing intermediate step. Plus you have to practically double the type annotation, which becomes really annoying if it's not just a tuple of two. ;-)

Now, this 'solution' brings up quite a strange warning in my code, although it's working. I do this in a `guard let` assignment.

```swift
guard let time: (min: Int, sec: Int) = someOptional?.quotientAndRemainder(dividingBy: 60) as? (Int, Int)

```

This gives:

```swift
Conditional downcast from '(quotient: Int, remainder: Int)?' to '(Int, Int)' is equivalent to an implicit conversion to an optional '(Int, Int)'

Replace ' as? (Int, Int)' with ''

```

I'm told to remove the cast completely. That would be my original code, which is not working. Funny guy, this compiler. ;) `as` and `as!` don't work either. Perhaps some complicated setting of brackets around… Stop! That doesn't make the code better readable.

I guess there is room for improvement on the language side.

---

<div class="post-metadata">

**Author:** ![DevAndArtist](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/devandartist/32/287_2.png) [@DevAndArtist](https://forums.swift.org/u/DevAndArtist)\
**Post date:** [December 12, 2018, 10:10am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/6 "2018-12-12T10:10:10Z")

</div>

Can you try if the example I previously wrote also works if you remove the last (Int, Int) and move the type you want to the end?

let final = something.method() as (x: Int, y: Int)

Something like this? Not sure if it compiles either. ;)

In case of the optinal you may try `as? (x: Int, y: Int)` directly?

I used these types because i can type them faster on the phone. Use the correct types instead.

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 10:29am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/7 "2018-12-12T10:29:01Z")

</div>

> [@DevAndArtist](#):
>
> let final = something.method() as (x: Int, y: Int)
> 
> Something like this? Not sure if it compiles either. ;)

Nope. Doesn't compile.  
Thanks for talking your time on this matter, BTW!^^

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [December 12, 2018, 10:42am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/8 "2018-12-12T10:42:48Z")

</div>

Tuple element labels (or lack of labels) are part of the tuple's type. Conversion is allowed between labeled and unlabeled tuples (with matching element types):

```swift
func test() {
    var t = (1, 2)
    var t1 = (a: 1, b: 2)
    var t2 = (c: 3, d: 4)
    
    print(type(of: t)) // (Int, Int)
    print(type(of: t1)) // (a: Int, b: Int)
    print(type(of: t2)) // (c: Int, d: Int)
    t = t1 // OK
    t = t2 // OK
    t1 = t // OK
    t2 = t // OK
    //t1 = t2 // ERROR: Cannot assign value of type '(c: Int, d: Int)' to type '(a: Int, b: Int)'
    //t2 = t1 // ERROR: Cannot assign value of type '(a: Int, b: Int)' to type '(c: Int, d: Int)'
    t1 = t2 as (Int, Int) // OK
    t2 = t1 as (Int, Int) // OK
}
test()

```

* * *

Some subtleties:

```swift
func test() {
    var t1 = (x: 1, 2)
    var t2 = (3, x: 4)
    
    print(type(of: t1)) // (x: Int, Int)
    print(type(of: t2)) // (Int, x: Int)
    
    t1 = t2 // OK
    print(t1) // (x: 4, 3)
    t2 = t1 // OK
    print(t2) // (3, x: 4)
}
test()

```

* * *

```swift
func test() {
    var t1 = (1, x: 2)
    var t2 = (x: 3, x: 4) // OK (perhaps surprisingly enough for being a bug: https://bugs.swift.org/browse/SR-8974)
    
    print(type(of: t1)) // (Int, x: Int)
    print(type(of: t2)) // (x: Int, x: Int)
    
    t2 = t1 // OK
    print(t2) // (x: 2, x: 1)
    t1 = t2 // OK
    print(t1) // (1, x: 2)
}
test()

```

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 11:04am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/9 "2018-12-12T11:04:04Z")

</div>

> [@Jens](#):
>
> ```swift
> var t1 = (a: 1, b: 2)
> var t2 = (c: 3, d: 4)
>     
> //t1 = t2 // ERROR: Cannot assign value of type '(c: Int, d: Int)' to type '(a: Int, b: Int)'
> //t2 = t1 // ERROR: Cannot assign value of type '(a: Int, b: Int)' to type '(c: Int, d: Int)'
> 
> ```

Do you think this is justified, desirable?

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [December 12, 2018, 11:22am UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/10 "2018-12-12T11:22:06Z")

</div>

I think it is somehow more desirable than what you ask for (blindly allow conversion between any tuples with matching element types disregarding their labels) because it would remove the use of / need for labels, at least from a type safety point of view.

I forgot to mention another subtle side of the current behavior:

```swift
func test() {
    var a = (x: 1, y: 2)
    var b = (y: 3, x: 4)
    
    a = b // OK (perhaps surprisingly)
    print(a) // (x: 4, y: 3)
    b = a // OK (perhaps surprisingly)
    print(b) // (y: 3, x: 4)
    
    print(a == b) // false (perhaps surprising that two values of different type can be checked for equality?)
    print(a == b as (x: Int, y: Int)) // true
    print(type(of: a) == type(of: b)) // false
}
test()

```

I don't think the above is desirable behavior and it will not compile if [tuple shuffling is deprecated](https://forums.swift.org/t/deprecating-tuple-shuffles-round-2/16884). But if what you ask for would be allowed, then I guess the above would have to compile, and the result would probably be different, I guess it would be like this:

```swift
// NOTE: Speculated alternative behavior if label-ignoring conversion was allowed:
func test() {
    var a = (x: 1, y: 2)
    var b = (y: 3, x: 4)
    
    a = b // OK
    print(a) // (x: 3, y: 4)
    b = a // OK
    print(b) // (y: 3, x: 4)
    
    print(a == b) // true
    print(a == b as (x: Int, y: Int)) // true
    print(type(of: a) == type(of: b)) // true ... I guess ... ?
}
test()

```

Which would arguably be even stranger than the current behavior. Also, would the type of a and b be different or the same?

I think the current behavior + deprecated tuple shuffles makes most sense, all aspects (that I can think of) taken into consideration.

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 12:23pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/11 "2018-12-12T12:23:33Z")

</div>

> [@Jens](#):
>
> at least from a type safety point of view.

Wouldn't that be 'just' a matter of scope, like in shadowing variables?

```swift
// so valuable function ;)
func foo(value: Int?) {
    if let value = value {
        print(value) // unwrapped local value
    }
    print(value) // original passed in optional value is still alive
}

```

Tuple elements can always be accessed by their index. The label, as I see it, is just a nice to have convenience to ease access and readability. Why shouldn't it be possible to shadow the labels or convert them, if I can do that in an intermediate label erasing step anyway? o\_O  
If the label really matters that much, what is the difference from a struct? The `quotientAndRemainder(dividingBy:)`function that gave me the intro could 'equally' well return a struct.

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 12:42pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/12 "2018-12-12T12:42:43Z")

</div>

> [@Jens](#):
>
> ```swift
> a = b // OK (perhaps surprisingly)
> b = a // OK (perhaps surprisingly)
> 
> print(a == b) // false (perhaps surprising that two values of different type can be checked for equality?)
> 
> ```
> 
> ```swift
> // NOTE: Speculated alternative behavior if label-ignoring conversion was allowed:
> func test() {
> var a = (x: 1, y: 2)
> var b = (y: 3, x: 4)
>     
> a = b // OK
> print(a) // (x: 3, y: 4)
> b = a // OK
> print(b) // (y: 3, x: 4)
>     
> print(a == b) // true
> print(a == b as (x: Int, y: Int)) // true
> print(type(of: a) == type(of: b)) // true ... I guess ... ?
> }
> test()
> 
> ```
> 
> Which would arguably be even stranger than the current behavior. Also, would the type of a and b be different or the same?

I find it rather strange that you annotate the status quo code three times with 'surprisingly' or 'surprising' but still thinks that the code where you don't find anything 'surprisingly' is still 'stranger'… ;)

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [December 12, 2018, 12:44pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/13 "2018-12-12T12:44:37Z")

</div>

How about the following, which is currently allowed, and will continue to be allowed even after [tuple shuffling is deprected](https://forums.swift.org/t/deprecating-tuple-shuffles-round-2/16884), and is caused by the `==` operator that accepts any two tuples with matching element types and ignores their labels:

```swift
func test() {
    let ten = 10
    let rq = (remainder: 3, quotient: 1)
    let qr = ten.quotientAndRemainder(dividingBy: 3)
    print(qr == rq) // true <--- What? So 3 * 1 + 3 == 10 ... !?
    print(type(of: rq) == type(of: qr)) // false
}
test()

```

IMHO it shouldn't even be OK to, without explicit intent, check two values of different types for equality like this.

---

<div class="post-metadata">

**Author:** ![torquato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/torquato/32/1203_2.png) [@torquato](https://forums.swift.org/u/torquato)\
**Post date:** [December 12, 2018, 1:12pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/14 "2018-12-12T13:12:11Z")

</div>

For me they are not different types, but two tuples containing two Ints. They only differ in the backyard by naming the elements.

```swift
let rq = (yellow: 3, blue: 1)
let qr = ten.quotientAndRemainder(dividingBy: 3)
print(qr == rq) // true <--- What? So 3 * 1 + 3 == 10 ... !?

```

Wait! Now, yellow and blue have the wrong quotient and remainder? It's a naming issue of variables.

If you explicitlly ask for these names, you get these names. That is my inclination…

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [December 12, 2018, 1:22pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/15 "2018-12-12T13:22:14Z")

</div>

The labels are meant to carry meaning, yellow and blue become less problematic (and more nonsensical) than remainder and quotient in reverse order. I think neither should compile and I've made my position clear and motivated it thoroughly above and would only repeat myself if I continued this debate : ).

---

<div class="post-metadata">

**Author:** ![Avi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/avi/32/2962_2.png) [@Avi](https://forums.swift.org/u/Avi)\
**Post date:** [December 12, 2018, 1:25pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/16 "2018-12-12T13:25:51Z")

</div>

I think you're not seeing tuples as types, but more of a convenient bundling of independent variables. To go back to `struct`s, you wouldn't expect the following to work:

```
struct S { let x: Int, y: Int }
struct T { let x: Int, y: Int }

let s: S = T() // error: wrong type

```

The two structs not only have the same members, in the same order, with the same types, they are also the same names. Yet, `S` and `T` are considered distinct types. The same applies to tuples. Tuple types are a combination of their elements' labels and types. Taking labels out of consideration would move tuples closer to being bundled variables, and not distinct types.

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [December 12, 2018, 1:29pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/17 "2018-12-12T13:29:07Z")

</div>

I think that tuples should remain types (and be more consistently so), and for the same reason I think that it is unfortunate that the following works, and will continue to work even if eg tuple shuffling is deprecated:

```swift
func test() {
    let a = (x: 1, y: 2)
    let b = (y: 1, x: 2)
    print(a == b) // true (!)
    print(type(of: a) == type(of: b)) // false
    print(a.x == b.x && a.y == b.y) // false
}
test()

```

---

<div class="post-metadata">

**Author:** ![Avi](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/avi/32/2962_2.png) [@Avi](https://forums.swift.org/u/Avi)\
**Post date:** [December 12, 2018, 1:35pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/18 "2018-12-12T13:35:24Z")

</div>

It's a little inconsistent, but one could view it as automatic synthesis of `==` for the two different tuple types. Again, illustrating with structs, because it's easier.

```
extension S {
   func ==(lhs: S, rhs: T) { return lhs.x == rhs.x && lhs.y == rhs.y }
}

extension T {
   func ==(lhs: T, rhs: S) { return lhs.x == rhs.x && lhs.y == rhs.y }
}

```

It's inconsistent, in that we don't do it for any types _except_ tuples. (And I am _not_ advocating we start! 🙃)

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [December 12, 2018, 3:27pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/19 "2018-12-12T15:27:38Z")

</div>

> [@torquato](#):
>
> Tuple elements can always be accessed by their index. The label, as I see it, is just a nice to have convenience to ease access and readability. Why shouldn't it be possible to shadow the labels or convert them, if I can do that in an intermediate label erasing step anyway? o\_O

In Swift, labels for tuple elements are part of the type.

As a convenience, Swift allows you implicitly to erase labels--that is, `let a: (Int, Int) = (x: 1, y: 2)`--and to add labels--that is, `let a: (x: Int, y: Int) = (1, 2)`. However, Swift does not allow you to assign a tuple with one set of labels to a variable of tuple type with a different set of labels. This is a deliberate design choice.

None of this has to do with tuple shuffling.

It sounds like you'd prefer a language where labels for tuple elements are not part of the type. That's not the case with Swift.

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [December 12, 2018, 4:05pm UTC](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756/20 "2018-12-12T16:05:33Z")

</div>

> [@xwu](#):
>
> Swift does not allow you to assign a tuple with one set of labels to a variable of tuple type with a different set of labels. This is a deliberate design choice.
> 
> None of this has to do with tuple shuffling.

It has, in that tuple shuffling allows what Swift otherwise does not allow, ie to "assign a tuple with one set of labels to a variable of tuple type with a different set of labels":

```swift
func test() {
    let a = (x: 1, y: 2)
    var b = (y: 3, x: 4)
    print(type(of: a) == type(of: b)) // false
    b = a // <-- Assigment between tuples of different types.
    print(b) // (y: 2, x: 1)
}
test()

```

EDIT: I guess you're right because you used "set" rather than "sequence/list" ...

[Next page](https://forums.swift.org/t/redeclaration-of-named-tuple-members/18756.md?page=2)
