为啥在 Swift 的单数返回表达式中使用闭包简写变量必须详尽无遗?
Posted
技术标签:
【中文标题】为啥在 Swift 的单数返回表达式中使用闭包简写变量必须详尽无遗?【英文标题】:Why does use of closure shorthand-named variables has to be exhaustive in a singular return expression in Swift?为什么在 Swift 的单数返回表达式中使用闭包简写变量必须详尽无遗? 【发布时间】:2017-03-26 22:10:55 【问题描述】:以下代码在 Swift 中是错误的。
func foo(closure: (Int, Int) -> Int) -> Int
return closure(1, 2)
print(foo(closure: $0))
func foo(closure: (Int, Int) -> Int) -> Int
return closure(1, 2)
print(foo(closure: return $0))
XCode Playground 给出的错误是Cannot convert value of type '(Int, Int)' to closure result type 'Int'
。
虽然下面几段代码完全没问题。
func foo(closure: (Int, Int) -> Int) -> Int
return closure(1, 2)
print(foo(closure: $0 + $1))
func foo(closure: (Int, Int) -> Int) -> Int
return closure(1, 2)
print(foo(closure: $1; return $0))
func foo(closure: (Int, Int) -> Int) -> Int
return closure(1, 2)
print(foo(closure: a, b in a))
似乎在闭包的参数由速记参数名称引用的情况下,如果闭包的主体仅由返回表达式组成,则必须彻底使用它们。为什么?
【问题讨论】:
相关:Why is the shorthand argument name $0 returning a tuple of all parameters?. 【参考方案1】:如果您只使用$0
,则假定闭包参数是一个元组而不是多个变量$0
、$1
等。因此您应该能够通过提取该元组的第一个值来解决此问题:
print(foo(closure: $0.0))
【讨论】:
【参考方案2】:您的“为什么”就像问“为什么美式足球场有 100 码长?”因为那是规矩。接受参数的匿名函数体必须明确确认所有参数。它可以通过以下三种方式中的任何一种来做到这一点:
使用$0
、$1
、...表示法来表示它们。
在in
行中使用参数名称表示它们。
在in
行中使用_
明确丢弃它们。
所以,让我们举一个比你的简单得多的例子:
func f(_ ff:(Int)->(Void))
如您所见,函数f
接受一个参数,也就是一个接受一个参数的函数。
那么,让我们尝试将一些匿名函数交给f
。
这是合法的,因为我们在 in
行中命名参数:
f
myParam in
这是合法的,因为我们接受使用$0
表示法的参数:
f
$0
这是合法的,因为我们在in
行中使用_
明确丢弃了参数:
f
_ in
但这不合法:
f
1 // error: contextual type for closure argument list expects 1 argument,
// which cannot be implicitly ignored
【讨论】:
问问题的原因难道不是隐藏规则,而不是规则吗?我相信我们都希望 Swift 的设计是有道理的 ;-) @CRD 就像 Swift 的许多规则一样,这一切都是为了让您明确承认自己知道自己在做什么。考虑override
;它什么也没增加(因为 Objective-C 不使用它),所以如果你覆盖一个继承的成员,“为什么”需要它?为了让你明确。
我认为您误解了我的评论,可能还不够清楚。实际上,我认为这与 Swift 中类型推断的工作方式有关(参见@Palle 的回答),这就是“为什么”——而不是因为它是规则。类型推断不必以这种方式工作,一种不同的方法可以支持 OP 的预期(但可能不是 Swift 所做的其他事情——这都是关于选择的)。 OP 提出了一个合理的问题。以上是关于为啥在 Swift 的单数返回表达式中使用闭包简写变量必须详尽无遗?的主要内容,如果未能解决你的问题,请参考以下文章