Тернарная операторская ассоциация
У меня возникают проблемы с пониманием концепции ассоциативности в контексте троичных операторов. В большинстве случаев троичные операторы выглядят так:
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 */
Следовательно, ассоциативность троичного оператора корректна, даже если вы вкладываете выражения троичного оператора. Позаботьтесь, однако, о том, что это приводит к ухудшению читабельности кода, и это даже настоятельно рекомендуется для этого в руководстве по языку - Основные операторы
...
Однако используйте троичный условный оператор с осторожностью. Его краткость может привести к сложному для чтения коду при чрезмерном использовании. Избегайте объединения нескольких экземпляров тернарного условного оператора в один составной оператор.
Тернарный оператор: не два унарных оператора, а собственный уникальный оператор
Тернарный оператор - это специальный оператор, который не имеет прямого отношения ни к одному из других операторов в Swift; все остальные принадлежат к семействам унарных и бинарных операторов.
Унарные операторы...
Бинарные операторы...
Тернарные операторы работают на три цели. Как и C, Swift имеет только один троичный оператор - троичный условный оператор (a? B: c).
Из руководства по языкам - Основные операторы.
Так как нам разрешено только определять наши собственные prefix
(одинарный) и infix
(бинарные) операторы в Swift, я подозреваю, что вам будет довольно трудно реализовать свой собственный истинный троичный оператор, поскольку вы ограничены использованием его в качестве двух отдельных унарных инфиксных операторов ?
а также :
, что, естественно, не совпадает с одним троичным оператором. (Вы всегда можете посмотреть на это несколько старое сообщение в блоге Нейта Кука, объясняющее, как имитировать троичный оператор с помощью двух бинарных операторов, однако, поскольку в Swift 3 необходимо удалить каррирование, я не знаю, будет ли это возможно для будущие версии Swift).