优先群高于封闭

时间:2017-01-18 15:07:59

标签: swift

我正在尝试使用高于闭包的优先级组在Swift中定义自定义运算符。特别是,我希望能够写下:

foo --> bar { 
    //... 
}

-->运算符返回一个函数,该函数采用() -> Void类型的闭包作为唯一参数。

然而,我只能得到

(foo --> bar) { 
    //... 
} 

上班。是否有一个运算符优先级可以使这个工作没有括号?

这是

的优先组
precedencegroup LongArrowPrecedence {
    associativity: left
    higherThan: AssignmentPrecedence
}

infix operator --> : LongArrowPrecedence

谢谢!

1 个答案:

答案 0 :(得分:5)

我们首先建立了一个完整且可验证的例子:

precedencegroup LongArrowPrecedence {
    associativity: left
    higherThan: AssignmentPrecedence
}

infix operator --> : LongArrowPrecedence

func -->(lhs: Int, rhs: Int) -> (() -> ()) -> () {
    return { print(lhs+rhs, terminator: ""); $0() }
}

除了使用此运算符的paranthesis-embraced有效调用的示例之外,紧接着调用-->返回的闭包。

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之后的一组parantheses)将尝试< em>调用到该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包装在parantheses中时,组合的包装表达式才构成postfix-expression,其上应用了以下function-call-argument-clause。

  

后缀表达式

     

Postfix表达式是通过应用后缀运算符或其他形式来形成的   postfix语法到表达式。 从句法上讲,每个主要的   表达式也是一个后缀表达式。

     

主要表达

     

主表达式是最基本的表达方式。他们可以   用作表达式,可以与其他表达式结合使用   令牌用于创建前缀表达式,二进制表达式和后缀   表达式。

您将无法绕过这一点,因为运算符优先级不适用于function-call-argument-clause;后者(及其“优先级”)由函数调用表达式的语法定义。