如果 Swift 'guard' 语句必须退出作用域,那么作用域的定义是什么?



我对代码块或'作用域'的定义感到困惑。Apple for guard文档是这样说的:guard语句的else块…

"必须转移控制以退出出现guard语句的代码块。"

其他在线资源说guard语句必须退出它所在的'作用域'。

所以看下面的示例代码:

func testGuardControlFlow () {
let x = 2
let y = 2
    func embededFunc () {
        if y == 2 {
            guard x == 1 else {
                print("oops, number is not 1")
                return
            }
            print ("from in embededFunc")
        }
        print ("I still want this to print even if x != 1")
    }
    embededFunc()
    print("Great, return still allows this to be printed.")
}
testGuardControlFlow()

根据我目前对'scope'的理解,代码

if y == 2 {....}

创建一个新的作用域,即在{}之间。在这个假设下,警卫只会逃离这个范围。但事实并非如此。此实例中的Guard将从它所在的函数中转义,无论它是否隐藏在if子句中。

我完全误解了'scope'的意思吗?作用域是指方法中包含的代码吗?如果是这样,If语句中存在的"空间"的正确术语是什么?

完全有可能实现您的设想,只是碰巧不是特定代码所做的。return总是退出一个方法,而不是局部作用域。为了实现您的愿望,您可以使用标签和break:

func testGuardControlFlow() {
    let x = 2
    let y = 2
    func embededFunc () {
        breakLabel:
        if y == 2 {
            guard x == 1 else {
                print("oops, number is not 1")
                break breakLabel
            }
            print ("from in embededFunc")
        }
        print ("I still want this to print even if x != 1")
    }
    embededFunc()
    print("Great, return still allows this to be printed.")
}
testGuardControlFlow()

添加到vadian的回答:

guard强制您使用控制转移语句退出作用域。有4种可供您选择:

  • returnthrow同时退出函数/方法
  • continue可以在循环内使用(while/for/repeat-while)
  • break可以在循环(while/for/repeat-while)中使用,以退出直接作用域。指定要中断的标签将允许你一次退出多个作用域(例如,跳出嵌套循环结构)。当使用标签时,break也可以在if范围内使用。

此外,您可以通过调用返回Never的函数来退出作用域,例如fatalError

这个约束实际上是一件好事,这也是您可能想要使用guard而不是if的原因。它的意思是:

  1. 它使您避免检查先决条件,但随后意外地通过,就好像您没有检查过一样

  2. 它让条件绑定更好地工作。举个例子:

    guard let nonOptional = anOptional() else { return }
    usesANonOptional(nonOptional)
    

    usesANonOptional只有在传递了非可选参数时才安全。如果anOptional返回nil,则守卫将失败,并且将确保您不可能调用usesANonOptional。这意味着nonOptional是已知的非可选的,并且会自动为您打开包装。

你对术语范围的理解是完全正确的。它基本上是两个(平衡的)大括号之间的空间。

文档中退出代码块的描述是最准确的。

要退出guard语句,可以使用控制转移语句returnbreakcontinuethrow

  • returnthrow退出整个函数或方法。
  • continuebreak退出当前作用域(例如switchforwhile)。

你误解了医生说的话。guard语句本身不退出任何作用域。你必须在guard语句内写一些语句,退出包含该guard语句的作用域。

return将退出作用域。在循环中,break或continue将退出作用域。在许多情况下,goto将退出停止。没有特定的语句来退出if语句的作用域,因此您需要一个goto语句或其他语句来退出循环或包含guard语句的函数。

最新更新