I am having trouble understanding the concept of associativity in the context of ternary operators. In most cases, ternary operators look like this:
a ? b : c
In this case, no associativity is needed to evaluate the expression. Sometimes though, Ternary Operators are nested:
a ? b : c ? d : e
a ? b : (c ? d : e) // : is right-associative
However, the nesting could also be inverted
a ? b ? c : d : e
a ? (b ? c : d) : e // : is left-associative
What is the best way to explain this phenomenon? Could you consider the associativity of the :
operator to be context-dependant, or am I missing something here?
The associativity question becomes relevant when one wants to define their own ternary operator, for example in Swift:
infix operator ? { associativity right precedence 120 }
infix operator : { associativity left precedence 130 }
The ternary operator is always right-associative
The ternary operator is right-associative, as we see in your first example (and as we see below, this is the only choice we have if we want to let the corresponding if-else
blocks to contain anything else than expressions that evaluate to booleans). Note that your second example leaves no room associativity, so this does it does not show an example of any left-associativity of the ternary operator.
/* 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 */
Hence, the ternary operator's associativity is well-defined even if you nest ternary operator expressions. Take care, however, that doing so tends decrease code readability, and it is even outright recommended against this in the 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.
The ternary operator: not two unary operators, but a unique operator of its own
The ternary operator is a special operator not really directly related to any of the other operators in Swift; all other belong to the families of unary and binary operators.
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).
From the Language Guide - Basic Operators.
Since we're only allowed to customly define our own prefix
(unary) and infix
(binary) operators in Swift, I suspect you will have quite difficult time implementing your own true ternary operator, since you're limited to using it as two separate unary infix operators ?
and :
, which is naturally not the same as a single ternary operator. (You could always look at this somewhat old blog post by Nate Cook, explaining how to mimic a ternary operator by using two binary operators, however as currying is to be removed in Swift 3, I don't know if this will be possible for future Swift versions).
来源:https://stackoverflow.com/questions/36319740/ternary-operator-associativity