这自然是合法的:
let closure: (Int, Int) -> () = { print($0 + $1) }
closure(1, 2) // 3
鉴于实施演进提案
在Swift 3中,以下内容不合法:
let closure: (a: Int, b: Int) -> () = { /* ... */ }
错误:函数类型可能没有参数标签
a
,请_
改用。
引用SE-0111:
函数类型只能根据形式参数和返回值的类型进行定义。
然而,奇怪的是(并根据上述错误消息的提示),这是合法的:
let closure: (_ a: Int, _ b: Int) -> () = { print($0 + $1) }
closure(1, 2) // 3
但是,据我所知,我们永远不能使用a
及b
以上(它们甚至不应该被允许,因为它们不是参数类型的一部分?)。
a
和b
(给出引用,我们不应该...),或者这可能是对SE-0111实施的疏忽?您正在观察的是能够为闭合类型定义“纯装饰性”参数标签的功能。如理由所述,这被接受为SE-0111的一部分:
为了回应社区的反馈,核心团队正在接受提案,并对其进行了修订,以允许在封闭类型中使用“纯修饰性”参数标签进行记录(如替代部分所述)。
在建议之后,这些修饰参数标签的语法进行了更改,要求参数标签为_
,以明确表明在呼叫站点未使用修饰标签。补充说明中对此进行了详细说明:
核心团队对SE-0111要求的特定修订版是,所有“化妆品”标签都必须包含API名称
_
。例如,将不允许这样做:var op : (lhs : Int, rhs : Int) -> Int
相反,应将其拼写为:
var op : (_ lhs : Int, _ rhs : Int) -> Int
尽管实际上在实践中,这会使化妆品标签相当无用,因为它们不会出现在呼叫站点甚至自动补全中-仅出现在实际的声明本身中。因此,他们自我记录的意图有些丢失。
Swift团队意识到了这一缺点,并将寻求在Swift 3之后进行纯加性更改,以纠正这种情况。
这是他们提出的草图(再次在附加的注释中):
首先,我们扩展变量,属性和参数的声明名称,以允许参数名称作为其声明名称的一部分。例如:
var op(lhs:,rhs:) : (Int, Int) -> Int // variable or property. x = op(lhs: 1, rhs: 2) // use of the variable or property. // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”. func foo(opToUse op(lhs:,rhs:) : (Int, Int) -> Int) { x = op(lhs: 1, rhs: 2) // use of the parameter } foo(opToUse: +) // call of the function
这将恢复表达闭包参数思想的能力,该闭包参数将标签作为声明的一部分,而不要求参数标签成为类型系统的一部分(例如,允许将运算符+传递给需要参数标签的内容) 。
其次,扩展函数类型的规则,以允许且仅当参数API标签用作允许参数标签的声明的类型时,才允许参数API标签,并将其解释为用于在基础声明中提供这些标签的糖形式。这意味着上面的示例可以拼写为:
var op : (lhs: Int, rhs: Int) -> Int // Nice declaration syntax x = op(lhs: 1, rhs: 2) // Same as above // API name of parameter is “opToUse”, internal name is "op(lhs:,rhs:)”. func foo(opToUse op : (lhs: Int, rhs: Int) -> Int) { x = op(lhs: 1, rhs: 2) // Same as above. } foo(opToUse: +) // Same as above.
提出的解决方案非常好地允许标签在呼叫站点使用,允许自记录参数标签,而不会使类型系统变得复杂。另外(在大多数情况下),它允许将表达标签的语法写在闭包的参数类型旁边,这是我们习惯于进行Swift 3之前的版本。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句