简体   繁体   English

学习Swift-inout函数-为什么要修改全局变量值?

[英]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. 我来自Java语言背景,我希望在Swift的inout中获得一些清晰度。

In Javascript, a function's parameter only exists within the scope of that function. 在Javascript中,函数的参数仅存在于该函数的范围内。 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. 之所以可行,是因为参数名称仅存在于greet函数的范围内。 So I can change the value of name. 因此,我可以更改name的值。

However, in Swift, I cannot do this: 但是,在Swift中,我不能这样做:

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: 解决方案是将其更改为“ inout”函数,该函数只能采用变量,即:

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. 但是,当我这样做时,它实际上会更改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. 这意味着inout函数不仅会在函数范围内修改PARAMETER的值,还会修改全局变量。

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. 第二个代码块(第一个Swift示例)阻止您更改name值的原因是因为在Swift 3中,所有参数都是常量。 In other words they are essentially all declared with let . 换句话说,它们基本上都是用let声明的。

Imagine your first Swift example as: 想象一下您的第一个Swift示例为:

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. 显然,您并没有真正let它,但这将帮助您记住参数是不可变的。 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. 使用inout通过“删除let”来更改参数,并允许您更改调用函数时使用的原始变量。

How would you modify only the variable 'name' inside the function greet? 您将如何只修改函数内部的变量“名称”?

You don't in Swift 3. The parameter is immutable. 您不在Swift 3中。该参数是不可变的。 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. func greet(name: String) {}函数name是一个常数,实际上它看起来像func greet(let name: String) {}因此您无法对其进行修改。 Let add a new variable and assign value of name to it: 让我们添加一个新变量并为其分配name值:

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

Just read some of the Swift docs. 只需阅读一些Swift文档。 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. (1)默认情况下,Swift中的参数为CONSTANTS,因此好像在该参数之前有一个let关键字。 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. (2)将您的功能更改为“ inout”功能会更改内容。 First off, it removes the 'let' constraint. 首先,它删除了“ let”约束。 Secondly, when you pass in an argument to the inout parameter, it is known as copy-in, copy-out. 其次,当您将参数传递给inout参数时,称为复制,复制。 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. 换句话说,没有像Javascript这样的功能,您只能在函数范围内简单地修改参数的值。

Because: 因为:

The parameter is either a CONSTANT (by default), 该参数可以是CONSTANT(默认),

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. 您使用的是inout函数,在这种情况下,参数是变量而不是常量,但该参数仅存在于将参数的原始值“传送”到可以修改的函数中,然后吐出的目的。作为新值返回给内存中原始变量占位符。

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. 换句话说,...(据我所知)在Swift中,无法仅在参数功能范围内修改参数的值。 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. 默认情况下,由于参数是常量而被禁止这样做,或者您正在使用inout函数,该函数仅在函数内部不修改参数的值...它正在修改GLOBAL名称空间的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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