Swift: how closure captures variables of value type?

Viewed 1160

Take a look at the following code snippet

struct Person{
  var name: String
  let surname: String
  var closure: (()->())?
   init(name: String, surname: String){
      self.name = name
      self.surname = surname
    
   }
}

var person = Person(name: "John",  surname: "Lennon")
let cl = {
   print(person.name)
}

person.name = "Bill"
cl()
print(person.name)

the output of the above snippet is

Bill
Bill

Can somebody explain how this happens? I thought that since closure is reference type and Person is a value type then when the closure is created it gets its own copy of the Person(since value types are copied on pass), so modifying outer Person should not affect Person that is captured by closure, but it seems that it doesn't work in this way. I'm new to swift and value types, so please don't judge my question too hard.
Thank you
P.S. I know that we can capture value variable explicitly using capture list and in this case modifying outer variable doesn't affect captured variable. The question is no about this. The question is about the fact that I thought that it should be have the same way even without explicit capture

1 Answers

The behaviour you expect only works when you explicitly pass in a variable to a closure like this:

var person = Person(name: "John",  surname: "Lennon")
let cl: (Person) -> () = { person in
    print(person.name)
}
cl(person)
person.name = "Bill"
cl(person)

When you implicitly capture a variable in a closure, that variable is always passed by reference. If you want to capture variables by value, you need to explicitly pass them in.

Related