A Swift tuple is a composite value comprised of zero or more values.
An instance of a tuple is written as a parenthesis delimited list of comma separated values, like so
(1, 2, 3)
The values in a tuple do not have to be of the same type, for example,
(true, 2, ("three"
))
The mutability of a tuple in Swift is determined by whether it has been assigned to a constant or a variable.
1.0 Types
The type of a tuple is a function of the number of values and their types and is written in the same way as a tuple but with type names rather than values.
1.1 Zero Values
The type of an empty tuple is written as an empty tuple, like so
let t0 : () = ()
In Swift the type Void is simply an alias for the type of an empty tuple, so you can also write
let tv : Void = ()
1.2 One Value
The type of a single value tuple is simply the type of the value [1], so this
let t1 : (String) = ("malin")
can also be written like this
let t1 : String = ("malin")
or like this
let t1 : (String) = "malin"
or, if you are feeling really adventurous, like this
let t1 : String = "malin"
1.3 More Than One Value
The type of a tuple with more than one value is more straight-forward.
For example, the type of the tuple
(true, 2, ("three"
))
is
(Bool, Int, (String))
2.0 Value Access
2.1 The Index Notation
The values comprising a tuple can be accessed using an index-like notation like this
let triple = (1, 2, 3)
let first = triple.0
The same notation can be use to modify a mutable tuple, for example
var mutableTriple = (1, 2, 3)
mutableTriple.2 = 5
2.1 Pattern Matching
The values comprising a tuple can also be accessed using pattern matching like this
let triple = (1, 2, 3)
let (x, y, z) = triple
which results in x
having the value 1, y
having the value 2, and z
having the value 3.
Values within a tuple can be ignored in a pattern by using an underscore (‘_
‘) like so
let triple = (1, 2, 3)
let (_, y, _) = triple
As before, y
has the value 2.
Pattern matching can also be used in an assignment statement like this
let fishes = ("cod", "dab", "eel")
var oneFish = ""
var twoFish = ""
var threeFish = ""
(oneFish, twoFish, threeFish) = fishes
(oneFish, _, _) = fishes
3.0 Assignment
Assignment of a tuple results in a copy being made, so
let fishes = ("cod", "dab", "eel")
var mutableFishes = fishes
mutableFishes.0 = "saithe"
println(fishes)
println(mutableFishes)
prints
(cod, dab, eel)
(saithe, dab, eel)
4.0 Named Values
The values in a tuple can also be named, like so
var fishes = (first:"cod", second:"dab", third:"eel")
They can then be accessed by their names
let first = fishes.first
and if the tuple is mutable also modified
fishes.first = "saithe"
It is also possible to use the index notation and pattern matching to access the values in a named tuple but this is not necessarily a good idea for reasons that will become apparent.
4.1 Named Values And Tuple Types
It is not entirely clear what the type of a tuple with named values is.
It is apparent that if declared explicitly it must include the names so if you try this
let namedFishes: (String, String, String) = (first:"cod", second:"dab", third:"eel")
you get a compiler error.
On the other hand this works
...
typealias namedFishesType = (first:String, second:String, third:String)
let namedFishes: namedFishesType = ("cod", "dab", "eel")
...
as does this
...
typealias namedFishesType = (first:String, second:String, third:String)
var namedFishes: namedFishesType = (first:"cod", second:"dab", third:"eel")
...
var unnamedFishes: (String, String, String) = ("flounder", "gudgeon", "hake")
namedFishes = unnamedFishes
...
and this
...
typealias namedFishesType = (first:String, second:String, third:String)
var namedFishes: namedFishesType = (first:"cod", second:"dab", third:"eel")
...
var unnamedFishes: (String, String, String) = ("flounder", "gudgeon", "hake")
unnamedFishes = namedFishes
so for the purposes of assignment unnamed and named tuple values whose elements are of the same type seem to be interchangeable.
In addition for the purposes of assignment the order of the names in a named tuple value does not seem to be significant, so
...
typealias namedFishesType = (first:String, second:String, third:String)
let namedFishes: namedFishesType = (first:"cod", second:"dab", third:"eel")
println(namedFishes)
...
prints
(cod, dab, eel)
and so does
...
typealias namedFishesType = (first:String, second:String, third:String)
let namedFishes: namedFishesType = (third:"eel", second:"dab", first:"cod")
println(namedFishes)
...
However, just to make things confusing, the order of the names in a named tuple type does seem to be significant, at least for the purposes of using the index notation and pattern matching, so
...
typealias namedFishesType = (first:String, second:String, third:String)
let namedFishes: namedFishesType = (first:"cod", second:"dab", third:"eel")
println("namedFishes.0 == \(namedFishes.0)")
let (first, second, third) = namedFishes
println("\(first) \(second) \(third)")
...
prints
namedFishes.0 == cod
cod dab eel
but
...
typealias reversedFishesType = (third:String, second:String, first:String)
let reversedFishes: reversedFishesType = (first:"cod", second:"dab", third:"eel")
println("reversedFishes.0 == \(reversedFishes.0)")
let (first, second, third) = reversedFishes
println("\(first) \(second) \(third)")
...
prints
reversedFishes.0 == eel
eel dab cod
which is why you might want to think twice about acessing named values in tuples using the index notation and/or pattern matching.
Finally, as already noted, the types of named values are significant when the names are the same, so you cannot do something like this
...
typealias namedFishesType = (first:String, second:String, third:String)
// DOES NOT COMPILE: names match, types do not match
let fishes: namedFishesType = (first:"cod", second:2, third:true)
...
as are the names when the types are the same, so you cannot do something like this either
...
typealias namedFishesType = (first:String, second:String, third:String)
// DOES NOT COMPILE: types match, names do not match
let namedFishes: namedFishesType = (one:"cod", two:"dab", three:"eel")
...
Notes
-
At first glance this seems a trifle odd but there is a possible explanation.
It may have to do with the function return value type in Swift.
The clue is the fact that Void is an alias for the type of an empty tuple.
Copyright (c) 2014 By Simon Lewis. All Rights Reserved.
Unauthorized use and/or duplication of this material without express and written permission from this blog’s author and owner Simon Lewis is strictly prohibited.
Excerpts and links may be used, provided that full and clear credit is given to Simon Lewis and justanapplication.wordpress.com with appropriate and specific direction to the original content.