三元运算符关联性
Posted
技术标签:
【中文标题】三元运算符关联性【英文标题】:Ternary Operator Associativity 【发布时间】:2016-07-19 02:24:42 【问题描述】:我无法理解三元运算符上下文中的关联性概念。在大多数情况下,三元运算符如下所示:
a ? b : c
在这种情况下,不需要关联性来评估表达式。但有时,三元运算符是嵌套的:
a ? b : c ? d : e
a ? b : (c ? d : e) // : is right-associative
不过嵌套也可以倒置
a ? b ? c : d : e
a ? (b ? c : d) : e // : is left-associative
解释这种现象的最佳方法是什么?您能否认为 :
运算符的关联性取决于上下文,还是我在这里遗漏了什么?
当人们想要定义自己的三元运算符时,关联性问题就变得相关了,例如在 Swift 中:
infix operator ? associativity right precedence 120
infix operator : associativity left precedence 130
【问题讨论】:
【参考方案1】:三元运算符总是右结合
三元运算符是右关联的,正如我们在您的第一个示例中看到的那样(正如我们在下面看到的,如果我们想让相应的 if-else
块包含除评估为布尔值)。请注意,您的第二个示例没有留下空间关联性,因此它没有显示三元运算符的任何左关联性示例。
/* example 1 */
a ? b : c ? d : e
==> right-ass. => a ? b : (c ? d : e), OK
==> left-ass. => (a ? b : c) ? d : e
/* |___|
\ not OK: since then both of these must be
booleans: that is restriction we don't have */
/* example 2 */
a ? b ? c : d : e
==> only-valid-splitup => a ? (b ? c : d) : e
(a ? b ? c) : d : e
/* |___|
\ not valid, there's no ? ? ternary operator */
a ? b ? (c : d : e)
/* |___|
\ not valid, there's no : : ternary operator */
因此,即使您嵌套了三元运算符表达式,三元运算符的关联性也是明确定义的。但是请注意,这样做会降低代码的可读性,甚至在 Language Guide - Basic Operators
中直接建议不要这样做...
但是,请谨慎使用三元条件运算符。它的 如果过度使用,简洁会导致代码难以阅读。 避免 将三元条件运算符的多个实例组合成 一个复合语句。
三元运算符:不是两个一元运算符,而是一个自己的唯一运算符
三元运算符是一种特殊的运算符,与 Swift 中的任何其他运算符都没有真正的直接关系;所有其他都属于一元和二元运算符家族。
一元运算符 ...
二元运算符 ...
三元运算符对三个目标进行操作。与 C 一样,Swift 只有一个三元运算符,即三元条件运算符 (a ? b : c)。
来自Language Guide - Basic Operators。
由于我们只允许在 Swift 中自定义定义自己的 prefix
(一元)和 infix
(二元)运算符,我怀疑您将很难实现自己的 true三元运算符,因为您仅限于将其用作两个单独的一元中缀运算符?
和:
,这自然与单个三元运算符不同. (您可以随时查看this somewhat old blog post by Nate Cook,解释如何通过使用两个二元运算符来模拟三元运算符,但是由于在 Swift 3 中将删除柯里化,我不知道这对于未来的 Swift 版本是否可行)。
【讨论】:
以上是关于三元运算符关联性的主要内容,如果未能解决你的问题,请参考以下文章