Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is swift inout parameter a variable or a pointer?

Tags:

swift

inout

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() ???

like image 267
Adeline Avatar asked Nov 12 '16 21:11

Adeline


People also ask

What is Inout parameters in Swift?

You write an in-out parameter by placing the inout keyword right before a parameter's type. An in-out parameter has a value that's passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.

What is Inout type in Swift?

All parameters passed into a Swift function are constants, so you can't change them. If you want, you can pass in one or more parameters as inout , which means they can be changed inside your function, and those changes reflect in the original value outside the function.

What is an Inout variable?

An InOut variable in a function header is for a variable that may be written as well as read within the function, but may also be written, as well as read outside the function.

What is in-out inout parameters in Swift?

We can define the parameters as in-out parameters. To define a parameter as in-out, swift provides an inout keyword before the parameter's type. The in-out parameter has the value changed inside the function and returned to replace the original value.


2 Answers

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

like image 120
Dalija Prasnikar Avatar answered Sep 29 '22 04:09

Dalija Prasnikar


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.

like image 23
H S Progr Avatar answered Sep 29 '22 04:09

H S Progr