Swift Tuples: Unexpected Result

Hey everyone,


I'm learning about Swift tuples and wrote the following code...


//Tuples
//let temperature = (1, 23, 2020, 40.3)
//let temperature = (month: 1, day: 23, year: 2020, avgTemp: 40.3)
var temperature = (month: 1, day: 23, year: 2020, avgTemp: 42.3)
let (_, day, _, avgTemp) = temperature
temperature.avgTemp = 46.2 //the compiler acknowledges the temp change here by reading 46.2 
let tempString = "Today's date is Janaury \(day)rd and the temperature is \(avgTemp) degrees."


The result is not as expected.


I was expecting "Today's date is Janaury 23rd and the temperature is 46.2 degrees."


The compiler is reading "Today's date is Janaury 23rd and the temperature is 42.3 degrees."


I'm not sure why this because I declared temperature as a variable and it reads avgTemp as '46.2' on line 6.


Could someone please help with this?

Replies

It is not a question of tuple, it a question of passing by value or by reference.


In your code:


var temperature = (month: 1, day: 23, year: 2020, avgTemp: 42.3)
let (_, day, _, avgTemp) = temperature
temperature.avgTemp = 46.2 //the compiler acknowledges the temp change here by reading 46.2
let tempString = "Today's date is Janaury \(day)rd and the temperature is \(avgTemp) degrees."


You set temperature.avgTemp at line 1, with the 42.3 value, by copying the value

In line 2, you copy the value (42.3) of temperature.avgTemp into avgTemp.

Then you change temperature at line 3 to 46.2, but that does not change avgTemp, because the value was passed, not the reference of temperature.avgTemp (pointer of temperature.avgTemp)

This is because Double are passed by values, not by reference (the same with any number, with Strings, struct…).

Changing temperature.avgTemp does not change the copy that was made before in avgTemp, which remains 42.3


Now consider this:


class MyTemp {
    var val: Double = 0
  
    init(_ value: Double) {
        self.val = value
    }
}

var someTemp = MyTemp(42.3)
var temperature = (month: 1, day: 23, year: 2020, avgTemp: someTemp)
let (_, day, _, theTemp) = temperature     // theTemp is an instance of class, it gets a reference of someTemp.avgTemp
let tempString = "Today's date is Janaury \(day)rd and the temperature is \(theTemp.val) degrees."
print(tempString)

someTemp.val = 46.2 //the compiler acknowledges the temp change here by reading 46.2
let tempString1 = "Today's date is Janaury \(day)rd and the temperature is \(theTemp.val) degrees."
print(tempString1)

temperature.avgTemp.val = 32.0 //the compiler acknowledges the temp change here by reading 46.2
let tempString2 = "Today's date is Janaury \(day)rd and the temperature is \(theTemp.val) degrees."
print(tempString2)

someTemp = MyTemp(35.0)
let tempString3 = "New Today's date is January \(day)rd and the temperature is \(theTemp.val) degrees."
print(tempString3)


You get:

Today's date is Janaury 23rd and the temperature is 42.3 degrees.

Today's date is Janaury 23rd and the temperature is 46.2 degrees.

Today's date is Janaury 23rd and the temperature is 32.0 degrees.

New Today's date is January 23rd and the temperature is 32.0 degrees.


What happens ?

Line 9 we create someTemp, an instance of MyTemp : this is objectA, with val 42.3

line 10, temperature.avgTemp contains objectA, as classes are passed by reference, not values

line 11, theTemp in t-uple contains the reference of temperature.avgTemp, that is also objectA, and you see on line 12 prints 42.3


line 15, when you change someTemp property, you change the property val of objectA

line 16: as temp1 is objectA, you get 46.2 printed


The same occurs line 19 to 21: you can change the value of object A by changing temperature.avgTemp property

theTemp which points to objectA gets the change.

You get 32.0 degrees line 21.


But on line 23, you create a new object objectB, instance of MyTemp, with value 35 and now someTemp is objectB

You have not changed objectA

But theTemp is still pointing to objectA. Hence, theTemp.val was not changed to 35.0, it remains 32.0


As a conclusion, it is not a tuple problem, it is a question of passing by reference or value.


You should read this:

https://developer.apple.com/swift/blog/?id=10

Did this solve your issue ?


If no, please tell what is the problem.

If yes, don't forget to close the thread.