这自然是合法的:
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实施的疏忽?答案 0 :(得分:4)
如果你删除了为参数命名的能力,那么你就会失去一个重要的人际交流方面,告诉未来的维护者或用户这个代码的目的,这些都是抱怨,而不是无理由的。这些参数。好吧,就外部参数名称而言, 的能力已被删除。但是通过使用内部参数名称让它打开以隐藏在编译器之外,我们至少可以恢复某些通信。
但是,我们无法恢复该通信的 ,因为内部参数未显示在代码完成中:
这被批评为新政权在这个问题上的一个缺陷,在我看来,这是正确的。
答案 1 :(得分:4)
您正在观察的是能够定义纯粹的化妆品"闭包类型的参数标签。如SE-0111所述,这被in the rationale视为一部分:
为响应社群反馈,核心团队正在接受该提案,其修订版允许在文档的封闭类型中使用“纯粹化妆品”参数标签(如the alternatives section中所述)。
在要求参数标签为_
的提案之后,这些装饰参数标签的语法已更改,以便明确表示化妆品标签未在呼叫站点使用。详情见an additional commentary:
核心团队要求SE-0111的具体修订是 应该要求所有“化妆品”标签都包含API名称
_
。 例如,不允许这样做:var op : (lhs : Int, rhs : Int) -> Int
相反,它应拼写为:
var op : (_ lhs : Int, _ rhs : Int) -> Int
虽然实际上,实际上,这使得化妆品标签相当无用,因为它们不会出现在呼叫现场甚至是自动完成 - 只是在实际的声明本身。因此,他们自我记录的意图有点丢失。
Swift团队意识到了这个缺点,并希望在Swift 3之后进行纯粹的附加改变,以纠正这种情况。
这里是他们提出的草图(再次,在the additional commentary中):
首先,我们扩展变量,属性和参数的声明名称,以允许参数名称作为其声明名称的一部分。例如:
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 标签当且仅当将它们用作声明的类型时 允许参数标签,并将其解释为糖形式 在基础声明上提供这些标签。这意味着 上面的例子拼写为:
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之前做。