`guard let foo = foo` 什么时候变得合法了? [英] When did `guard let foo = foo` become legal?
问题描述
早在 2016 年 11 月,我就发布了一个问题,询问为什么我不能使用 guard 创建一个使用与可选变量相同名称的变量的解包版本,就像使用 if let 一样:
Back in November of 2016 I posted a question asking why I couldn't use guard to create an unwrapped version of a variable using the same name as the optional, like you can with if let:
链接:为什么不是guard let foo = foo 有效?
Link: Why isn't guard let foo = foo valid?
当我写这个问题时,下面的代码将无法编译,并显示定义与先前值冲突"的错误:
When I wrote that question, the code below would fail to compile with an error that "Definition conflicts with previous value":
//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
// Check if the current viewController exists
print(String(describing: viewController))
guard let viewController = viewController else {
return nil
}
print(String(describing: viewController))
return viewController
}
但是,我刚刚在工作中发现了一些代码可以做到这一点,现在它可以毫无怨言地编译并执行我想要它做的事情!运行时,打印语句显示 foo 在防护之前是可选的,而在防护之后是未包装的可选:
However, I just found some code at work that does this, and it now compiles without complaint and does what I want it to do! When run, the print statements show that foo is an optional before the guard, and an unwrapped optional after:
viewController = Optional(<TrochoidDemo.ViewController: 0x7ff16a039a00>)
viewController = <TrochoidDemo.ViewController: 0x7ff16a039a00>
(如果您想尝试一下,我将测试函数 guardTest(_:)
添加到我最新的开源项目中.它在 Github 上的 https://github.com/DuncanMC/TrochoidDemo)
(I added the test function guardTest(_:)
to my latest open source project if you want to try it out. It's available on Github at https://github.com/DuncanMC/TrochoidDemo)
我很高兴这个结构现在可以按照我想要的方式工作,但对为什么现在是合法的以及何时发生变化感到困惑.
I'm happy that this construct now works as I want it to, but confused as to why it's now legal, and when the change occurred.
有没有人知道最近语言定义的变化使这个结构在以前没有的地方工作?
Is anybody aware of a recent change to the language definition that makes this construct work where it didn't before?
推荐答案
TL;DR
guard let foo = foo
如果 foo
定义在另一个作用域中,则它是合法的.
guard let foo = foo
is legal if foo
was defined in another scope.
来自您链接问题的示例:
The example from your linked question:
func test()
{
let a: Int? = 1
guard let a = a else{
return
}
print("a = \(a)")
}
仍然不起作用,因为 guard
语句试图在同一范围内创建另一个变量 a
.
still doesn't work because the guard
statement is trying to create another variable a
in the same scope.
这个例子:
//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
// Check if the current viewController exists
print(String(describing: viewController))
guard let viewController = viewController else {
return nil
}
print(String(describing: viewController))
return viewController
}
与此相同的原因:
func test(a: Int)
{
print(type(of: a)) // Int
let a = 3.14
print(type(of: a)) // Double
}
函数的参数定义在不同的作用域中,所以 Swift 允许你创建一个同名的局部变量.
The parameter to the function is defined in a different scope, so Swift allows you to create a local variable with the same name.
这篇关于`guard let foo = foo` 什么时候变得合法了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!