三元运算符结合性
Ternary Operator Associativity
我无法理解三元运算符上下文中的关联性概念。在大多数情况下,三元运算符如下所示:
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 }
三元运算符总是右结合的
三元运算符是右结合的,正如我们在您的第一个示例中看到的(如下所示,如果我们想让相应的 if-else
块包含任何内容,这是我们唯一的选择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
中完全建议不要这样做
...
Use the ternary conditional operator with care, however. Its
conciseness can lead to hard-to-read code if overused. Avoid
combining multiple instances of the ternary conditional operator into
one compound statement.
三元运算符:不是两个一元运算符,而是它自己的唯一运算符
三元运算符是一个特殊的运算符,与 Swift 中的任何其他运算符都没有真正的直接关系;所有其他都属于一元和二元运算符家族。
Unary operators ...
Binary operators ...
Ternary operators operate on three targets. Like C, Swift has only one ternary operator, the ternary conditional operator (a ? b : c).
来自Language Guide - Basic Operators.
由于我们只允许在 Swift 中自定义定义我们自己的 prefix
(一元)和 infix
(二元)运算符,我怀疑您将很难实现您自己的 true 三元运算符,因为您只能将其用作 两个独立的一元中缀 运算符 ?
和 :
,这自然与 单个三元 运算符不同。 (您总是可以查看 this somewhat old blog post by Nate Cook,解释如何通过使用两个二元运算符来模拟三元运算符,但是由于在 Swift 3 中将删除柯里化,我不知道这是否可行用于未来 Swift 版本)。
我无法理解三元运算符上下文中的关联性概念。在大多数情况下,三元运算符如下所示:
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 }
三元运算符总是右结合的
三元运算符是右结合的,正如我们在您的第一个示例中看到的(如下所示,如果我们想让相应的 if-else
块包含任何内容,这是我们唯一的选择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
中完全建议不要这样做...
Use the ternary conditional operator with care, however. Its conciseness can lead to hard-to-read code if overused. Avoid combining multiple instances of the ternary conditional operator into one compound statement.
三元运算符:不是两个一元运算符,而是它自己的唯一运算符
三元运算符是一个特殊的运算符,与 Swift 中的任何其他运算符都没有真正的直接关系;所有其他都属于一元和二元运算符家族。
Unary operators ...
Binary operators ...
Ternary operators operate on three targets. Like C, Swift has only one ternary operator, the ternary conditional operator (a ? b : c).
来自Language Guide - Basic Operators.
由于我们只允许在 Swift 中自定义定义我们自己的 prefix
(一元)和 infix
(二元)运算符,我怀疑您将很难实现您自己的 true 三元运算符,因为您只能将其用作 两个独立的一元中缀 运算符 ?
和 :
,这自然与 单个三元 运算符不同。 (您总是可以查看 this somewhat old blog post by Nate Cook,解释如何通过使用两个二元运算符来模拟三元运算符,但是由于在 Swift 3 中将删除柯里化,我不知道这是否可行用于未来 Swift 版本)。