以下一段代码在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提供的错误是无法转换'(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}))
似乎在闭包的参数由缩写参数名称引用的情况下,如果闭包的主体只包含返回表达式,则必须使用它们。为什么呢?
答案 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
}
答案 1 :(得分:2)
如果你只使用$0
,假设闭包参数是一个元组而不是多个变量$0
,$1
等等。所以你应该能够解决这个问题该元组的第一个值:
print(foo(closure: {$0.0}))