Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a function a value type or a reference type in Swift? And Why?

Tags:

swift

Consider this function:

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

Here I am assigning this function to another variable

var mathFunction: (Int, Int) -> Int = addTwoInts

Here addTwoInts is a value type or reference type? And why?

like image 923
Nilanshu Jaiswal Avatar asked Nov 23 '18 16:11

Nilanshu Jaiswal


2 Answers

Closures and functions are Reference types. This is stated in the Swift language documentation: Closures

like image 132
CPR Avatar answered Oct 05 '22 10:10

CPR


I would say that a function type fits best with the definition of a reference type:

Reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used.

However I don't think this is a particularly useful distinction to make, IMO it would also be valid to make the argument that functions are value types (as technically speaking they consist of a pointer and a reference, both of which are copied when the function value is passed about).

The more useful distinction to make is that functions have reference semantics, meaning that it's possible to observe some kind of shared state between instances. This is not the same as being a reference type – it's possible for value types to have reference semantics, and for reference types to have value semantics.

For example here's a value type with reference semantics:

var foo = 0
struct S {
  var bar: Int {
    get { return foo }
    nonmutating set { foo = newValue }
  }
}

let s = S()
let s1 = s
s.bar += 1
print(s.bar)  // 1
print(s1.bar) // 1

Both s and s1 share global state, and this is observable by mutating it.

And here's a reference type with value semantics:

final class C {
  let foo = 0
}

let c = C()
let c1 = c
print(c.foo)  // 0
print(c1.foo) // 0

Although both c and c1 share state, this isn't directly observable because that shared state is immutable.

So, why do functions have reference semantics? Because they can contain captured variables, which is shared mutable state that can be observed.

For example:

func makeFn() -> () -> Int {
  var foo = 0
  return {
    foo += 1
    return foo
  }
}

let fn = makeFn()
let fn1 = fn
print(fn())  // 1
print(fn1()) // 2
like image 45
Hamish Avatar answered Oct 05 '22 12:10

Hamish