2

I got the solution but can't understand why it works.

my struct is QuizBrain()

whenever i try to use this code, i got an error:

Cannot use mutating member on immutable value: function call returns immutable value

btw the checkAnswer method is mutated.

code:

let userGotItRight = QuizBrain().checkAnswer(pressedAnswer)

The solution is creating an object from that struct and using it. Can someone explain why it is necessary to create an object?

code:

var quizBrain = QuizBrain()

let userGotItRight = quizBrain.checkAnswer(pressedAnswer)
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
Jarvis
  • 53
  • 3
  • 5
    The difference lies between `var` and `let`. When you declare `var`, it can be mutated. `let` is constant hence cannot be mutated. Without assigning to a `var`, it is treated as a `let` constant because there isn't a "variable" to be mutated. – Ricky Mo May 18 '22 at 04:31

1 Answers1

2

It is actually mix of let vs var and class vs struct. Here are some examples. Firstly lets declare your code as both struct and class:

struct QuizBrainStruct {
    var answer: String?
    mutating func checkAnswer(_ str: String) {
        self.answer = str
    }
}

class QuizBrainClass {
    var answer: String?
    func checkAnswer(_ str: String) {
        self.answer = str
    }
}

let pressedAnswer = "pressed"

In this example we I will use QuizBrainStruct() and QuizBrainClass() which are similar but not the same. Your QuizBrain() is defined as struct, therefore if you make this statement:

let userGotItRight = QuizBrainStruct().checkAnswer(pressedAnswer)// would fail with: Cannot use mutating member on immutable value is a 'let' constant

It is basicelly treated the same way as declaring let variable and then calling the function on in as following:

let s = QuizBrainStruct()
s.checkAnswer(pressedAnswer) // would fail with: Cannot use mutating member on immutable value: 's' is a 'let' constant

Your workoroud works if you declare it as a var, because values of var can be mutated:

var s2 = QuizBrainStruct()
s2.checkAnswer(pressedAnswer)

However there is more into the topic and that is that Struct is passed as value, therefore "s" cannot be mutated. If you declare it as a class (which is passed as reference) . You can do the following with no errors:

let userGotItRight = QuizBrainClass().checkAnswer(pressedAnswer)

Here is the difference why:

let s1 = QuizBrainStruct()
let s2 = s1 // s1 value is a new value and it is copy of s1

let c1 = QuizBrainClass()
let c2 = c1 // c1 value is reference to c1 (same value)

For more info about struct vs class you can read following swift doc . You can read more about value and reference type here: value vs reference passing

Mr.SwiftOak
  • 1,469
  • 3
  • 8
  • 19