一行闭包没有返回类型

25

在Swift中,如果一个闭包只包含一条语句,它会自动返回从该语句返回的值。

但在某些情况下,这种行为并不是很自然。让我们看一个例子:

func StringReturningFunc() -> String {
    return "Test String"
}

// Error: Cannot convert the expressions type '() -> $T0' to type 'String'
let closure: () -> () = {
    StringReturningFunc()
}

正如您所看到的,即使闭包只应调用一个简单的函数,它也会尝试自动返回其返回值,该返回值的类型为String,并且与返回类型void不匹配。

我可以通过以下方式实现闭包体来防止这种情况:

let _ = StringReturningFunc()

这感觉非常奇怪。

有没有更好的方法来解决这个问题,还是我只能忍受它?


我不明白这个的意义,当你的字符串返回函数明确返回一个字符串时,你怎么能说闭包返回()呢? - user1971598
@EdgarAroutiounian 他试图执行函数并丢弃返回值,但是单行闭包中有一个隐式的 return 语句。 - Erik
一个令人惊讶的例子是:class A { func method() {} }; var a: A? = nil; var closure: () -> () = { a?.method() }。这是同样的错误,但是由于VoidVoid?之间的不匹配而引起的。 - Sulthan
@Sulthan 这其实并不奇怪。a?.method() 的意思是“如果 a 不为 nil,在其上调用 method,如果为 nil,则返回 nil”。因此 void 必须是可选的(void 不等同于 nil)。 - IluTov
我理解了,但这并不意味着它很明显。 - Sulthan
显示剩余3条评论
2个回答

26

发生这种情况的原因是单行表达式闭包的速记方式。在你编写的闭包中有一个隐含的 'return'。

let closure: () -> () = {
    StringReturningFunc()
    return
}

按照那样的方式编写应该可以工作


2
感谢这个提示!如果 OP 仍希望它成为单行,可以使用 let wrapped: () -> Void = {stringReturningFunc(); return} 完成。 - Erik
2
难道真的没有其他方法可以不必显式地调用return来完成这个任务吗? - Mike
11
如果Swift编译器能检测到闭包应该返回Void类型并因此不尝试返回第一个语句,那么这个问题不就可以解决了吗?对于所有其他不返回Void类型的闭包,它都可以使用隐式返回。 - Richard Venable
1
@SandyChapman 这个令人困惑的编译器错误是可以修复的编译器错误,但我仍然认为这种约定是好的。但在我最初回复你的评论中,我提出了一种改进方法,使得 () -> Void = { x() }() -> Void = { x(); return } 是相同的。如果他们检测到意图是返回 Void,他们不应该假设隐式返回。当不返回 Void 时,Swift 的隐式返回很棒 - 在其他语言中的替代方案是生成编译器错误“缺少返回”,但那有什么优势呢? - Richard Venable
2
截至Xcode Beta版本6.3(6D520o),该问题似乎已经得到解决。“单表达式闭包的隐式返回”现在也适用于返回Void以外的其他内容的表达式。 - nmdias
显示剩余6条评论

0

这个怎么样... ;)

@discardableResult func StringReturningFunc() -> String {
    return "Test String"
}

// Error: Cannot convert the expressions type '() -> $T0' to type 'String'
let closure: () -> () = {
    StringReturningFunc()
}

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