我正在尝试在Swift中定义一个自定义运算符,其优先级高于闭包。我特别希望能够写:
foo --> bar {
//...
}
-->
运算符返回一个函数,该函数将() -> Void
类型的闭包作为唯一参数。但是,我只能得到
(foo --> bar) {
//...
}
去工作。是否有运算符优先级可以使该操作不带括号?
这是
precedencegroup LongArrowPrecedence {
associativity: left
higherThan: AssignmentPrecedence
}
infix operator --> : LongArrowPrecedence
谢谢!
最佳答案
我们首先建立一个完整且可验证的示例:
precedencegroup LongArrowPrecedence {
associativity: left
higherThan: AssignmentPrecedence
}
infix operator --> : LongArrowPrecedence
func -->(lhs: Int, rhs: Int) -> (() -> ()) -> () {
return { print(lhs+rhs, terminator: ""); $0() }
}
以及使用此运算符的使用括号括起来的有效调用的示例,之后紧接着是对
-->
返回的闭包的调用。let foo = 1
let bar = 2
// OK
(foo --> bar) {
print(" is the magic number")
} // 3 is the magic number
// OK
((-->)(foo, bar)) {
print(" is the magic number")
} // 3 is the magic number
这并不能告诉我们太多,但是如果我们研究以下失败的案例
// ERROR: cannot call value of non-function type 'Int'
foo --> bar {
print(" is the magic number")
} // 3 is the magic number
// ... equivalent to
// ERROR: cannot call value of non-function type 'Int'
foo --> bar({
print(" is the magic number")
}) // 3 is the magic number
我们意识到这里的问题不是“优先于低于闭包”,而是function-call-argument-clause(在任何postfix-expression之后的一组括号)将尝试调用该postfix-expression,就好像postfix-expression是一个方法/功能/关闭。如果postfix-expression是不可调用的,或者在function-call-argument-clause中的调用与可调用对象的任何重载都不匹配,则编译器将产生错误。
42() // ERROR: cannot call value of non-function type 'Int'
let foo = 42
foo() // ERROR: cannot call value of non-function type 'Int'
func bar() {} // ERROR: argument passed to call that takes no arguments
bar(42)
因此,提供给从
-->
返回的闭包的尾随闭包在这里是不相关的:它只是返回闭包的一个参数,而关键问题是Swift会将一个函数调用参数子句应用于postfix-expression,该子句会立即在子句之前。在您的示例中,bar
构成了该后缀表达式,只有将foo --> bar
包裹在括号中,合并的包装后的表达式才会构成后缀表达式,以下函数调用参数子句将应用到该表达式中。您将无法规避这一点,因为运算符优先级不适用于函数调用参数子句。后者(及其“优先级”)由函数调用表达式的语法定义。
关于swift - 优先组高于闭包,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41722819/