当闭包(似乎)永远无法访问时,为什么要在闭包的类型注释中使用“内部参数标签”?

dfrib

背景

这自然是合法的:

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

但是,据我所知,我们永远不能使用ab以上(它们甚至不应该被允许,因为它们不是参数类型的一部分?)。

  • 是否有任何理由使上面的最终代码段合法?我们可以使用或访问“内部参数标签”ab(给出引用,我们不应该...),或者这可能是对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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在闭包参数中使用“ &&”?

为什么要在代码中考虑使用JavaScript闭包?

为什么Apple的闭包声明缺少参数标签

为什么我需要在所有传递闭包中使用ConfigureAwait(false)?

闭包参数的终身注释

为什么参数通过闭包失效?

访问闭包内部的方法

在闭包中使用元类型

过滤时,闭包错误无法使用类型为(((_)-> _))的参数列表调用'filter'[NSDictionary]

为什么在Jenkinsfile中的DSL闭包中使用`env`或`param`时需要关键字`this`

上下文闭包类型 '() -> Text' 需要 0 个参数,但在闭包主体中使用了 1

为什么要在javascript闭包中打印此值?

为什么“ for .. in”允许闭包?

如何在响应闭包内部访问Alamofire请求参数?

在onerror属性中使用闭包似乎不起作用

具有显式参数的闭包内部不能使用匿名闭包

在Swift的闭包内部使用unown闭包

创建使用try运算符的闭包时,如何解决错误“需要类型注释”?

闭包参数上未使用的类型参数

如何在闭包内部访问“ this”?

为什么不能修改内联方法的闭包参数?

JavaScript-为什么此闭包不保存参数?

在闭包内部使用函数参数快速处理

为什么要使用IFFE闭包而不是常规闭包?

Spock 中闭包内部的参数捕获

数组内部带有参数的闭包

如何访问已在闭包中使用use()传递的ReflectionFunction中的参数

为什么不能在类型别名上使用@autoclosure到函数闭包类型?

为什么在Common Lisp中,闭包无法捕获封装函数的参数?