function labels/parameters

Simple Swift question. I can make my label visible to the caller and give a label variable name that is used internal to my function. ( thats my understanding 😁)


But I noticed if I declare a variable with the same internal name within the function, the compiler does not create an error. It just replaces it after the declearation without errors. For instance, I would have expected internalTest:Float and internalTest:Array to create a compiler warning or error. Probably should be an error.


func test(externalTest internalTest:Float) {

print("test =\(internalTest)")


var internalTest:[Int] = [1,2,3] //Conflicts with method parameter?

internalTest.append(4)

print("test =\(internalTest)")

}


//Call test method

test(externalTest:1.0)


Playground prints:


internalTest = 1.0

internalTest = [1, 2, 3, 4]

Answered by QuinceyMorris in 173397022

No, by design it's not an error. It's called variable "shadowing".


Shadowing, when it does not produce compile errors, can certainly be a source of bugs. OTOH it's a convenient way of avoiding having think of new names for temporary variables, so it's a convenient pattern once you're used to it. Originally, shadowing was only allowed in some contexts, such as shadowing an instance property with a local variable, but it's gradually become available everywhere.


The best argument for it is in optional binding:


func test(externalTest internalTest:Float?) {
     if let internalTest = internalTest {
     … }
}


This "removes" the optionality but keeps the semantic connection with the parameter. You can also use it when you want modify a parameter variable locally within the function:


func test(externalTest internalTest:Float) {
     var internalTest = internalTest
     while internalTest > 0 {
          …
          internalTest -= …
     }
}


Again, this helps clarify that you're "really" iterating on the incoming parameter.


Once you're aware of the shadowing pattern and get used to using it, you'll find you rarely make a mistake with unintended shadowing.

Accepted Answer

No, by design it's not an error. It's called variable "shadowing".


Shadowing, when it does not produce compile errors, can certainly be a source of bugs. OTOH it's a convenient way of avoiding having think of new names for temporary variables, so it's a convenient pattern once you're used to it. Originally, shadowing was only allowed in some contexts, such as shadowing an instance property with a local variable, but it's gradually become available everywhere.


The best argument for it is in optional binding:


func test(externalTest internalTest:Float?) {
     if let internalTest = internalTest {
     … }
}


This "removes" the optionality but keeps the semantic connection with the parameter. You can also use it when you want modify a parameter variable locally within the function:


func test(externalTest internalTest:Float) {
     var internalTest = internalTest
     while internalTest > 0 {
          …
          internalTest -= …
     }
}


Again, this helps clarify that you're "really" iterating on the incoming parameter.


Once you're aware of the shadowing pattern and get used to using it, you'll find you rarely make a mistake with unintended shadowing.

ok, I'll let that sink in some. 😁 Good example with the optional binding. That had me confused before.


Thanks again!

function labels/parameters
 
 
Q