Adeline
Adeline

Reputation: 475

Is swift inout parameter a variable or a pointer?

I feel a bit lost using swift inout parameter in the following code:

var shouldContinue: Bool = true

func doSomeWork1(shouldContinue: inout Bool)
{
    while shouldContinue
    {
        // ERROR: the compiler wants: doSomeWork2(shouldContinue: &shouldContinue)
        doSomeWork2(shouldContinue: shouldContinue)
    }
}

func doSomeWork2(shouldContinue: inout Bool)
{
    while shouldContinue
    {

    }
}

Why does the compiler want doSomeWork2(shouldContinue: &shouldContinue) instead of the compiler wants: doSomeWork2(shouldContinue: shouldContinue) ? isn't shouldContinue already a pointer in the scope of doSomeWork1() ???

Upvotes: 6

Views: 4572

Answers (2)

H S W
H S W

Reputation: 7119

From: Matt Neuburg Book “iOS 13 Programming Fundamentals with Swift.” :

If we want a function to alter the original value of an argument passed to it, we must do the following:

  • The type of the parameter we intend to modify must be declared inout.
  • When we call the function, the variable holding the value to be modified must be declared with var, not let.
  • Instead of passing the variable as an argument, we must pass its address. This is done by preceding its name with an ampersand (&).

Our removeCharacter(_:from:) now looks like this:

 func removeCharacter(_ c:Character, from s: inout String) -> Int {
  var howMany = 0
  while let ix = s.firstIndex(of:c) {
    s.remove(at:ix)
    howMany += 1
  }
 return howMany
}

And our call to removeCharacter(_:from:) now looks like this: var s = "hello" let result = removeCharacter("l", from:&s) After the call, result is 2 and s is "heo". Notice the ampersand before the name s when we pass it as the from: argument. It is required; if you omit it, the compiler will stop you. I like this requirement, because it forces us to acknowledge explicitly to the compiler, and to ourselves, that we’re about to do something potentially dangerous: we’re letting this function, as a side effect, modify a value outside of itself.

Upvotes: 1

Dalija Prasnikar
Dalija Prasnikar

Reputation: 28517

Being a pointer is only side-effect of optimization process for inout parameters. They actually work in different manner using copy-in copy-out behavior. So inside function that parameter is treated just like regular variable, not pointer. If you pass it to another function that takes inout parameter you have to mark it as such.

In-out parameters are passed as follows:

When the function is called, the value of the argument is copied.

In the body of the function, the copy is modified.

When the function returns, the copy’s value is assigned to the original argument.

This behavior is known as copy-in copy-out or call by value result. For example, when a computed property or a property with observers is passed as an in-out parameter, its getter is called as part of the function call and its setter is called as part of the function return.

As an optimization, when the argument is a value stored at a physical address in memory, the same memory location is used both inside and outside the function body. The optimized behavior is known as call by reference; it satisfies all of the requirements of the copy-in copy-out model while removing the overhead of copying. Write your code using the model given by copy-in copy-out, without depending on the call-by-reference optimization, so that it behaves correctly with or without the optimization.

In-Out Parameters

Upvotes: 11

Related Questions