我正在尝试在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/

10-13 09:25