简体   繁体   中英

Learning Swift - inout functions - Why do they modify the global variable values?

I'm coming from a Javascript background and I'm looking for some clarity on inout with Swift.

In Javascript, a function's parameter only exists within the scope of that function. So for instance I could do this without a problem.

function greet(name) {
 name = "randomDude";
 return name
}

greet("Barry");

This works because the parameter name only exists within the scope of the greet function. So I can change the value of name.

However, in Swift, I cannot do this:

func greet(name: String) {
   name = "Ardvark"
   print(name)
}

greet(name: "Drew")

The solution would be to change it to an 'inout' function, which can only take a variable, ie:

func greet(name: inout String) {
       name = "Ardvark"
       print(name)
    }

var name = "Drew"    
greet(name: name)

However, when I do this, it actually CHANGES the value of var name. Meaning the inout function doesn't modify only the value of the PARAMETER within the scope of the function, but modifies the global variable.

Is this just something I have to accept? Is there a reason it modifies the global variable? How would you modify only the variable 'name' inside the function greet?

Thanks

The reason the 2nd block of code (1st Swift example) prevents you from changing the value of name is because in Swift 3, all parameters are constants. In other words they are essentially all declared with let .

Imagine your first Swift example as:

func greet(let name: String) {
   name = "Ardvark"
   print(name)
}

Obviously you don't really put let there but that will help you remember that parameters are immutable. This prevents you from changing the value by mistake. If you want to change it just inside the function, use a new variable:

func greet(name: String) {
   let anotherName = "Ardvark"
   print(anotherName)
}

Using inout changes the parameter by "removing the let" and allowing you to change the original variable used when calling the function.

How would you modify only the variable 'name' inside the function greet?

You don't in Swift 3. The parameter is immutable. Assign it to a new variable inside the function.

In the func greet(name: String) {} function name is a constant, actually it looks like func greet(let name: String) {} so you can't modify it. Let add a new variable and assign value of name to it:

func greet(name: String) {
    var newName = name
    newName = "Ardvark"
    print(newName)
}

Just read some of the Swift docs. Came to two conclusions.

(1) By default, parameters in Swift are CONSTANTS, so it's as if there is a let keyword before the parameter. Meaning inside the function, the parameter value cannot be changed, or an error will be thrown.

(2) Changing your function to an 'inout' function changes things. First off, it removes the 'let' constraint. Secondly, when you pass in an argument to the inout parameter, it is known as copy-in, copy-out. The argument's value is copied in memory, passed through the function, modified in the function, and the new value is assigned to the original variable that was passed as an argument.

These are two distinct types of functions if you think about it. In other words, there is no functionality like in Javascript where you can simply modify the parameter's value inside the scope of the function ONLY.

Because:

The parameter is either a CONSTANT (by default),

OR...

You are using an inout function, in which case, the parameter is a variable as opposed to a constant, but that parameter only exists for the purpose of 'transferring' an argument's original value into a function where it can be modified, and then spit back out as a new value to the original variable placeholder in memory.

In other words... There is no way (that I know of) in Swift to only modify a parameter's value INSIDE the scope of it's function. You are either prohibited from doing so by default because the parameter is a constant, or you are using an inout function, which isn't modifying the parameter's value inside the function only... It is modifying the GLOBAL namespace's value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM