Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Tuples - Different from struct and from each other?

Tags:

swift

tuples

How different are tuples in swift from structures? (1)

As I understand, both tuples and structures can be sent by value instead by reference in function calls, returns, right?

Also, I know that if have

var A : StructureX
var B : StructureX

I know that structure A and B have the same Type, which is StructureX. But...

let A : (Int, String)
let B : (Int, String)

Are A and B tuples the same Type? (2) What are the advantages about using Tuples instead of structures? (3)

like image 580
rodrigogq Avatar asked Dec 09 '14 16:12

rodrigogq


People also ask

Is tuple a struct?

Since tuples are structs there is no much point in making them immutable. The readonliness of a struct is a property of the whole variable. If a tuple variable is assignable, it can be changed to contain any value regardless of the readonliness of individual fields.

Is a tuple a struct or class?

Value tuples are tuple types introduced in the . NET Framework 4.7 to provide the runtime implementation of tuples in C# and struct tuples in F#. They differ from the tuple classes, such as Tuple<T1>, Tuple<T1,T2>, etc., as follows: They are structures (value types) rather than classes (reference types).

Can tuples have different data types Swift?

You can create tuples from as many values as you want and from any number of different data types.

What is a tuple in Swift?

In Swift, a tuple is a group of different values. And, each value inside a tuple can be of different data types. Suppose we need to store information about the name and price of a product, we can create a tuple with a value to store name (string) and another value to store price (float)


2 Answers

I find it's easiest to conceptualize Swift Tuples as "Anonymous Structs" with a few critical differences. They behave similarly, but a struct has a formal definition and allows more control over mutability, while tuples allow for pattern matching.

Similarities Between Tuples and Structs

  • Both may have any number of members of any type, including closures
  • Both can be constructed inline (see typealias in the code below)
  • Both prevent mutation of any members if declared as constants
  • If a tuple has labeled members, both structs and tuples allow member access by label

Differences Between Tuples and Structs

  • Structs require a definition before use
  • Structs do not allow pattern matching against their members
  • Structs allow mutability of members declared as variables if the instance is a variable
  • Tuples do not allow mutating functions or functions that refer to any of its members
  • Tuples may not implement Protocols
  • If a tuple has anonymous members, its members can be accessed by index, unlike structs

Some code for a playground illustrating these differences and similarities

// All commented code causes a compilation error. Uncomment to view error messages.

struct StructureX {
    let a: Int = 0
    var b: String = "string"
}

//
// Struct member variability
//
var structureA: StructureX = StructureX()
let structureB: StructureX = StructureX()
//structureA.a = 2              // declared as a constant, instance is variable
structureA.b = "allowed"        // declared as a variable, instance is variable
//structureB.a = 2              // declared as constant, instance is constant
//structureB.b = "not allowed"  // declared as constant, instance is constant
structureA = structureB         // these are the same type
structureA


//
// A tuple can't be used as a literal to construct a struct.
//
//let StructureC: StructureX = (a: 17, b: "nope")


//
// Typealias a labeled tuple and it can be constructed similarly to a struct
//
typealias StructureT = (a: Int, b: String)
var structureD: StructureT = StructureT(a: 0, b: "asdf")
structureD
//structureD = structureA       // but they are distinct types



let emptyTuple: () = ()         // philosophically, isn't this the definition of Void?
print(emptyTuple)               // prints as ()
let single: (Int) = (23)
//let namedSingle: (a: Int) = (a: 42)


//
// Tuple Labeled Member Access
//
var labeledTupleA: (a: Int, b: String) = (a: 0, b: "string")
labeledTupleA.0 = 5
labeledTupleA.a
labeledTupleA

var check: (a: Int, b: String)
check = labeledTupleA           // same type
check

//
// Tuples can have functions/closures
//
let labeledTupleB: (Int, String, fun: () -> Void) = (0, "string", { () -> Void in
    print("hi")
})
labeledTupleB.1
labeledTupleB.fun()
//labeledTupleB.0 = 10          // this tuple is a constant, so all of its members are constant


//
// Tuples with members of the same type, but differet labels are not of the same type
//
var labeledTupleC: (c: Int, d: String) = (c: -1, d: "fail")
//labeledTupleC = labeledTupleA
//labeledTupleC = labeledTupleB


//
// Tuples with anonymous members matching the type pattern of a labeled member tuple are of equivalent type
//
var unlabeledTuple: (Int, String) = (0, "good")
unlabeledTuple = labeledTupleA
unlabeledTuple = labeledTupleC


//
// Tuples with closures may not refer to sibling members
//
var labeledTupleD: (de: Int, df: (Int) -> Void) = (de: 0, df: { (num: Int) -> Void in
    //de += num
    //self.de += num
    print(num)
})

labeledTupleD.de
labeledTupleD.df(1)


//
// Tuples allow pattern matching, Structs do not
//
//switch structureA {
//case (let i, let s):
//    print(i, s)
//default:
//    break
//}

switch labeledTupleD {
case (_, let closure):
    closure(123)
default:
    break
}
like image 168
Ralfonso Avatar answered Sep 28 '22 11:09

Ralfonso


I'm not sure the official terminology around tuples however, you declare them as if they were a special kind of type:

let A : (Int, String)

Maybe we could say that A is now a variable of type tuple? However, not all tuples are the same. If you declare variable of type tuple and try to assign it a tuple with parameters that differ in count, sequence, or type you'll get a compiler error. This will fail

let A : (Int, String) = ("Bob", 1234, 4.0) 

Though this works fine:

let A : (Int, String) = (1234, "Bob")

Of course this strong type safety is also enforced with structs.

As far as the advantages, here are some thoughts on the differences I'm aware of.

Structures require that you define them before using them. Tuples, on the other hand, let you return an arbitrary list of values. How is this useful? I have an iPad app with a shopping cart view controller in it. There is a summary view in the cart view that displays a current status of what's in the cart at any given time--sometimes just normal items, but RMA items and items on re-order are also potentially in the cart. I have a method on my shopping cart class that returns a tuple containing cart count, RMA count, re-order count, and total count. I don't have to declare a structure to get back all four values. It's very convenient:

class Cart : NSManagedObject {
    ...
    var totals : (cartCount:Int, rmaCount:Int, reorderedCount:Int, totalCount:Int) {
        let cart = ...    // Calculate cart count
        let rma = ...     // Calculate rma count
        let reorder = ... // Calculate reorder count
        let total = cart + rma + reorder // Add them all up

        return (cart, rma, reorder, total)
    }
}

In my cart view:

let cartValues = cart.totals
self.summaryView.cartCountLabel.text = "\(cartValues.cartCount)"       
self.summaryView.rmaCountLabel.text = "\(cartValues.rmaCount)"    
self.summaryView.reorderCountLabel.text = "\(cartValues.reorderedCount)"    
self.summaryView.totalCountLabel.text = "\(cartValues.totalCount)"

There may be other reasons, but convenience is the most compelling one for me to prefer tuples in this scenario.

like image 42
Matt Long Avatar answered Sep 28 '22 12:09

Matt Long