You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift自定义优先级组运算优先级异常是否为Bug?

这可不是Swift的Bug哦,是个很有意思的运算符解析细节!咱们结合你的代码和Swift的规则一步步拆解清楚:

precedencegroup PowerPrecedence { 
    lowerThan: BitwiseShiftPrecedence 
    higherThan: AdditionPrecedence 
    associativity: right 
}
infix operator ^^ : PowerPrecedence
extension Int {
    static func ^^ (lhs: Int, rhs: Int) -> Int {
        var result = 1
        for _ in 1...rhs {
            result *= lhs
        }
        return result
    }
}
print(3 ^^ 2 * 3) // 报错
print(2 ^^ 2 ^^ 2 * 2) // 输出32(右结合时)

核心逻辑:歧义的触发条件

Swift只会在不同优先级组的运算符共享同一个操作数,且无法通过结合性明确运算顺序时,才会抛出Adjacent operators are in unordered precedence groups错误。如果表达式能通过结合性拆分成无歧义的子表达式,就不会报错。

1. 右结合时的两条语句

第一条语句:3 ^^ 2 * 3

这个表达式的结构是操作数 ^^ 操作数 * 操作数,中间的2是^^和*的共享操作数。由于你定义的PowerPrecedence和Swift内置的MultiplicationPrecedence没有任何优先级关联(既没设lowerThan也没设higherThan),Swift根本不知道该先算3^^2还是2*3——完全歧义,所以触发编译错误,这和你预期的一致。

第二条语句:2 ^^ 2 ^^ 2 * 2

当^^是右结合时,连续的同一个运算符会优先按照结合性规则处理:2 ^^ 2 ^^ 2会被解析为2 ^^ (2 ^^ 2),这是一个无歧义的链式运算(同一个运算符的右结合逻辑),算出结果16。此时整个表达式简化成了16 * 2——这就是普通的乘法,不存在共享操作数的歧义,所以能正常编译运行,输出32。

2. 改为左结合时的情况

如果你把associativity改成left,第二条语句2 ^^ 2 ^^ 2 * 2就会出现歧义:
左结合规则下,Swift会尝试先处理左边的^^,但此时第二个2同时是第一个^^的右操作数、第二个^^的左操作数;而第三个2又同时是第二个^^的右操作数、*的左操作数。Swift无法判断:

  • 是先算(2^^2) ^^ 2再乘以2?
  • 还是先算2*(2^^2)再用2求幂?
    因为PowerPrecedence和MultiplicationPrecedence依然没有优先级关联,这种歧义没法通过左结合消除,所以两条语句都会触发编译错误。

最后总结

这完全是Swift运算符解析规则的正常表现:右结合的链式运算帮你把^^部分先打包成一个完整的子表达式,避免了和*共享操作数的歧义;而左结合时,这种歧义无法避免,因此报错。

内容的提问来源于stack exchange,提问作者user2158697

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:32:36