Why is foo = foo unprotected?

In Swift, you can use if you enable optional binding to expand the optional parameter into a constant or variable with the same name:

func test() { let a: Int? = 1 if let a = a { print("a = \(a)") } } 

For everything contained inside an if let , optional a expanded into a regular int.

Similarly, I can use the guard instruction to achieve a similar effect.

 func test() { let a: Int? = 1 guard let requiredA = a else{ return } print("a = \(requiredA)") } 

However, I cannot use code like this: guard let a = a else :

 func test() { let a: Int? = 1 guard let a = a else{ return } print("a = \(a)") } 

Why not?

In the guard instruction, if the condition of the guard operator is not fulfilled, the else condition is satisfied and you exit the current area. If the condition succeeds, a new variable / constant is created from the closing bracket of the watchdog to the end of the current area.

Why can't I do the exact same trick when matching an optional to a variable / constant with the same name for the rest of the current scope?

PS: I understand that this question is not perfect for this site. I am open to suggestions as to where it would be better for this question.

+4
source share
1 answer

The reason you cannot do this:

 func test() { let a: Int? = 1 guard let a = a else{ return } print("a = \(a)") } 

is that guard creates a new variable in the same scope, so you have two variables named a in the same scope. One is Int and the other is Int? . This is not allowed.

The error you encountered The definition conflicts with the previous value , exactly the same as if you did it:

 func test() { let a: Int? = 1 let a = a! } 

Compare this to:

 func test() { let a: Int? = 1 if let a = a { print("a = \(a)") } } 

In this case, the new variable a , which is Int , exists only in the new scope of the if then clause, so this works.


From the comments:

But I submit to you that the section of code after closing and to the end of the covering area is actually an internal area.

I can understand that you want this to be so, but it is not. If so, then you can do it, but it also gives an error:

 func test() { let a: Int? = 1 guard let b = a else{ return } print("b = \(b)") let a = 5 // Definition conflicts with previous value print("a = \(a)") } 

The beauty of the guard is that it does not create new applications, and you avoid creating the pyramid of death, which occurs when you reuse if let to expand options (and in the process of creating new areas).


See the next question. When did let let foo = foo become legal? to get more information on this topic.

+10
source

Source: https://habr.com/ru/post/1263333/


All Articles