Swift中IIFE的类型推断

4

IIFE(立即调用的函数表达式)是 JavaScript 中常用的模式。Swift 似乎也支持这种模式。如下所示:

let one = { 1 }
/// one: () -> Int

显式类型声明和常量返回的函数可以很好地工作。

let one:Int = { $0 }(1)
/// one: Int

但常数返回函数无法推断其自身类型。

let one = { $0 }(1)
/// SourceKitService
///    Terminated
///
/// Editor functionality
/// temporarily limited.

我需要像在shell中一样强制运行它。

// inferred.swift

#!/usr/bin/xcrun swift

var i:Int = 0
let id = { $0 }(i)

println(id)

当出现文本“Whemphasized textile silgen closureexpr SIL function @_TF8inferredU_FRSiSi for expression at [./inferred.swift:4:10 - line:4:15] RangeText="{ $0 }"”时,发生了段错误。[1] 29364 ./inferred.swift

我是否遗漏了些内容或者语法有误?


看起来像是编译器崩溃了。你正在使用哪个版本的Xcode? - tng
@tng beta 5。最新版本。 - seoh
1
编译器被太多选项搞糊涂了,你的代码没有问题,除了提交错误报告外,你无能为力。 - Bryan Chen
1个回答

3
我相信我曾经看到过一些关于Swift实现这个结构的内容被称为“叫做闭包”,但现在我找不到了。
请注意你的第一个例子:
let one = { 1 }

“...不是所谓的闭包。它定义了一个闭包,但没有调用它。因为它没有参数,所以您可以在括号后放置一个空参数列表来同时定义和调用它:”
let one = { 1 }()

你也应该能够使用类型推断来完成这个任务:
let one = { $0 }(1)  // one: (Int) = 1

let i = 1            // i: Int = 1
let one = { $0 }(i)  // one: (Int) = 1

这些对我在 beta 5 上有效,不过如果使用 var 声明而不是 let,就会失效。(任何时候,当你看到编译器或 SourceKit 崩溃时,最好去报告错误。)
调用的闭包可以很好地设置懒初始化存储属性——首次获取属性时运行闭包。例如,你会在 Xcode 项目模板中注意到这些内容,用于设置 Core Data 堆栈:
lazy var managedObjectContext: NSManagedObjectContext? = {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil {
        return nil
    }
    var managedObjectContext = NSManagedObjectContext()
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
}()

在这种情况下,必须明确给出类型 -- 因为闭包可能返回nil,它的返回类型必须是可选的,但类型检查器无法确定是哪种类型的可选。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接