这将编译以下内容:

let badger = get_closure()

func get_closure() -> (Int) -> Void {
  return { (x: Int) -> Void in
    print(x)
    if x > 4 {
      return
    } else {
      badger(x + 1)
    }
  }
}

badger(1)

这不适用于循环引用错误:

let badger = get_closure()

let get_closure = { () -> (Int) -> Void in
  return { (x: Int) -> Void in
    print(x)
    if x > 4 {
      return
    } else {
      badger(x + 1)
    }
  }
}

badger(1)

为什么?我认为func语法只是对第二种更明确的语法的补充.

推荐答案

事实是,第一个可以工作的是一个长期存在的bug/quirk in the compiler,而不是一个预期的功能.它是基于undefined behavior的,编译器很难检测到.您可以通过将您的工作代码包装在一个函数中来演示它是顶级声明的怪癖,并且可以看到它的失败与您的第二个示例非常相似:

func f() {
    let badger = get_closure()

    func get_closure() -> (Int) -> Void {  // ERROR: Closure captures 'badger' before it is declared
        return { (x: Int) -> Void in
            print(x)
            if x > 4 {
                return
            } else {
                badger(x + 1)
            }
        }
    }

    badger(1)
}

badger这样的top-level, global个声明的主要特点是,它们的计算很慢,所以赋值实际上发生在函数声明之后.在您的第二个示例中,两个变量都是惰性的,因此返回顺序.但依赖这一事实是危险的,正如链接的论坛帖子中所讨论的那样.

在探索微妙的SWIFT行为时,我总是建议构建一个命令行应用程序,并将测试代码放在函数中,以消除playground 和顶级可执行代码的奇怪之处.(在这种情况下,操场并不重要,但它经常被提到.)

Swift相关问答推荐

阴影动画的动画不流畅

减go 用SWIFT struct 填充的NSCountedSet

String.Index encodedOffset已弃用,但建议的替代方案不起作用

如何根据 DatePicker 中选定的日期实现 TabView 页面切换?

UIView.convert(_ point:to:)的意外行为

如何使用Swift宏和@Observable和@Environment?

在Equatable上引用运算符函数==要求Dictionary.Values符合Equatable

将弱引用作为类函数引用传递时,弱引用无法按预期工作

在领域 SwiftUI 异常中使用 Apple 登录:无法识别的 Select 器发送到实例

确定路径是否相交的有效方法

Swift 全局函数列表

如何在 SwiftUI 中正确实现Collection 夹?

在 Swift 中,如何查看 Process() 传递给 shell 的字符串?

Xcode swift ui 错误KeyPathComparator仅在 macOS 12.0 或更高版本中可用

通用枚举菜单 SwiftUI

如何快速截取 UIView 的屏幕截图?

无法推断泛型参数的参数

无法将 NSAttributedString.DocumentAttributeKey 类型的值转换为 .DocumentReadingOptionKey

如何快速从另一个视图控制器重新加载表格视图

将 UIImage 剪成圆形