Overriding variables in functions
Why does n't redeclaringoutput
inside this if-statement generate an error?
let output = 0
if counter < message.count {
let output = counter //This should throw an error, right?
counter += 1
} ...
The scope inside the if statement is aware of output
, as shown here, when trying to change the value output
instead of re-declaring:
let output = 0
if counter < message.count {
output = counter //ERROR: Cannot assign to value: 'output' is a 'let' constant
counter += 1
} ...
source to share
There is no error because it is perfectly legal to declare a variable inside a closure with the same variable name that was declared outside the closure. It shadows the "external declared variable".
If your sample code is inside class
, you can still access the "external declared variable" with self
:
class Foo {
let output = 0
func baa() {
let output = 1
print(output)
print(self.output)
}
}
Using this:
let foo = Foo()
foo.baa()
prints:
1 0
source to share
let output = counter
declares a new variable (output) in the statement scope if
that has nothing to do with the variable output
declared outside.
Edit
The code snippet below shows that the variables are output
not the same despite their name. The changed value is a local variable output
, not an external one.
var message = [String]()
let output = 2
var counter = -1
if counter < message.count {
let output = counter //This should throw an error, right?
print("local output value is:\(output)") // here the local output value is -1 not 2.
counter += 1
}
source to share
The first example is the case of tracking variables . This happens when the code has multiple blocks of blocks. In the first example:
let output = 0 //outer scope block
if counter < message.count {
let output = counter //inner scope block
counter += 1
} ...
In the internal visibility block, a new constant 'output' has been declared with the keyword 'let'. This output constant is only valid in this if block. This means that the same name is used as the "if" statement above. This is variable shading.
For the second example:
let output = 0
if counter < message.count {
output = counter //ERROR: Cannot assign to value: 'output' is a 'let' constant
counter += 1
} ...
The error occurs because defining something with "let" makes it a constant. It cannot be changed. In this case, there is only one "output" constant. It was declared above the if statement, and it is a constant. Thus, it cannot be changed after it has been assigned a value.
So in the first example there are 2 "output" constants, one of which is only valid in the if statement. In the second example, there is only 1 "output" constant.
source to share
Curly brackets represent the scope. In the inner scope, it is always right to obscure the variable name from the outer scope.
let output = // ... [A]
[class, func, if, for, do, etc.] {
let output = // ... [B, overshadows A]
// *
}
You've done a self-limiting thing, in a sense, in that the code at the point *
can no longer reference output
A; it is overshadowed by output
B. But this is not illegal. On the contrary, it is an important thing to do and it would be foolish to forbid it.
source to share