Найти в Дзене
Physics.Math.Code

Пару слов о тернарном операторе

Заменив кучу if-else одной строчкой, решить проблему поиска максимума из трех элементов, не создавая массива:

return (a > b)? ((a > c)? a : c) : (b > c)? b : c;

Мелочь, а приятно. Бокал кофе за элегантность тернарного оператора!

Кстати, такое возможно не только в си-подобных язык программирование. Можно и в Python, к примеру.

Синтаксис тернарного в Python: a if condition else b
Реализация возможна такая:

def getMax(a, b, c):
return (a if (a > c) else c) if (a > b) else (b if (b > c) else c)

Также в Python можно индексировать кортеж:
( falseValue, trueValue )[ bool(condition) ]
Пример для двух переменных:
def getMax2(a, b):
return (b, a)[bool(a > b)]

Лично мне не очень нравится тернарный оператор в Python, т.к. рассматривать логику приходится с середины выражения. В си-подобных языках этот оператор более последователен и прост в понимании. В целом, эксперты программирования не советуют усложнять логику своих программ. Так как большинство сложных проектов делают несколько людей, то ваш код в первую очередь должен быть понятен для других людей. Поэтому не всегда нужно использовать замудренные конструкции языка. А если вы их используете, то напишите вескую причину этому в комментарии перед методом.

Само название, как вы, вероятно, уже догадались, произошло от латинского слова ternarius — «тройной». Итак, в большом количестве языков программирования тернарный оператор является операцией, возвращающей свой второй или третий операнд в зависимости от значения логического выражения, заданного первым операндом.

Обычно тернарная условная операция ассоциируется с операцией ? : , используемой в си-подобных языках программирования.

К наиболее популярным языкам, содержащим тернарную условную операцию, можно отнести C, C++, JavaScript, Objective-C, C#, D, Java, ECMAScript, Perl, PHP, Python,Tcl, Ruby, Verilog, Turbo Basic и другие. Своим появлением непосредственно в тернарной инфиксной форме эта операция обязана языку Алгол-60, в котором она имела синтаксис if o1 then o2 else o3 и затем языку BCPL (o1 -> o2, o3) вместо привычного теперь o1 ? o2 : o3.

Прототипом же этой операции, в свою очередь, является условная функция cond языка Лисп, записываемая по правилам Лиспа в префиксной форме и имеющая произвольное количество аргументов.

(cond (<тест1> <результат>...)...)

Эта функция воспринимает любое число списков как аргументы. Она оценивает первый элемент списка (по очереди) до тех пор, пока не встретится отличный от nil. Затем вычисляется то выражение, которое следует за тестом и возвращает значение последнего выражения в подсписке. Если в подсписке только одно выражение (например, <результат> отсутствует), возвращается значение выражения <тест>. COND - основная функция условия в AutoLISPе.

Пример для понимания: Проверить, содержится ли заданный элемент X в заданном списке LST, и если нет, то добавить этот элемент к списку.

(COND ( (MEMBER X LST) T )
( T (CONS X LST) )
)

Безотносительно к определённому языку программирования тернарную операцию можно определить так:

логическое выражение ? выражение_1 : выражение_2

Алгоритм работы операции следующий:

  • Вычисляется логическое выражение.
  • Если логическое выражение истинно, то вычисляется значение выражения выражение_1 , в противном случае — значение выражения выражение_2 .
  • Вычисленное значение возвращается.

Нужно обратить внимание, что вычисляется только одно из выражений: выражение_1 или выражение_2 . Это соответствует принципу ленивых вычислений, и сделано не столько для оптимизации, сколько для расширения возможностей: так, выражение x < 0 ? 0 : sqrt(x) абсолютно корректно.

Ленивые вычисления (англ. lazy evaluation, также отложенные вычисления) — применяемая в некоторых языках программирования стратегия вычисления, согласно которой вычисления следует откладывать до тех пор, пока не понадобится их результат.

Отложенные вычисления позволяют сократить общий объём вычислений за счёт тех вычислений, результаты которых не будут использованы. Программист может просто описывать зависимости функций друг от друга и не следить за тем, чтобы не осуществлялось «лишних вычислений».

Ленивые вычисления естественным образом легли на функциональную парадигму программирования, поскольку функциональные языки программирования, реализующие отложенные вычисления, зарекомендовали себя как инструменты, удобные для прототипирования и быстрой разработки программного обеспечения, а также для проектирования электронно-вычислительных устройств.

Тернарная условная операция используется в выражениях для получения одного из двух вариантов в зависимости от условия.

alarm_time = today in [SUNDAY, MONDAY] ? 12.00 : 8.00

В этом примере условному программируемому электронному будильнику проставляется время, в которое он должен звонить, в зависимости от текущего дня недели. Нужно заметить, что пример снова приведён для некоторого абстрактного алгоритмического языка программирования.

В следующем примере вычисляется значение простейшего дельта-символа.

y = x == 0 ? 1 : 0

В следующем примере данная операция использована в ситуации, не связанной с присваиванием:

sprintf(
Title,
"%s %s",
tv_system == TV_PAL ?
"PAL" :
"SECAM",
tv_input ?
Tv_Name[ tv_input - 1 ]:
"TEST"
);

В данном случае эквивалентная конструкция с использованием if-then-else потребовала бы записи вызова функции sprintf четыре раза. Либо, в качестве альтернативы, потребовалось бы написать аналогичный по назначению (но формально не эквивалентный) код с использованием двух дополнительных временных переменных либо нескольких последовательных вызовов sprintf.

В Си тернарная операция имеет следующий синтаксис:

o1 ? o2 : o3

Как известно, в Си нет логического типа данных (в C99 появился логический тип _Bool). Поэтому операнд o1 должен быть числом (целым или вещественным) или указателем. Сначала вычисляется именно его значение. Оно сравнивается с нулём и, если оно не равно нулю, вычисляется и возвращается o2, в случае равенства — o3. Операнды o2 и o3 могут быть различных, вообще говоря, несовпадающих типов, включая void.

В следующем примере вычисляется максимальное из чисел a и b:

min = (a > b) ? a : b;

а здесь максимальное из чисел a, b и c:

max = (a > b)? ((a > c)? a : c) : (b > c)? b : c;

В C++ тернарная условная операция имеет тот же синтаксис, что и в Си. Однако за счёт наличия разницы между инициализацией и присваиванием, бывают ситуации, когда операцию ? : нельзя заменить конструкцией if-then-else, как, например, в следующем случае:

-2

Здесь переменная sout инициализируется в момент объявления результатом работы тернарной операции. Подобного эффекта не удалось бы достичь простым присваиванием в том или ином случае.

Кроме того, тернарная условная операция может быть применена в левой части оператора присвоения:

-3

В этом примере, если логическая переменная cond в строке 5 будет содержать значение true, то значение 1 будет присвоено переменной a, иначе, оно будет присвоено переменной b.

В некоторых сложных выражениях с тернарными операторами нужны скобки, чтобы компилятор правильно мог распознать структуру по символам ":". В противном случае логика вашего выражения сломается. Поэтому я бы советовал сначала отладить код с блоками if-else. А уже потом при необходимости переделать его на тернарный оператор.

Больше интересных статей читай по хэштегу #article@physics_math в группе Physics.Math.Code.Books

Помощь по физике, математике, программировании, информатике и другим техническим предметам найдете в
Репетитор | IT mentor

Наш канал в telegram : @physics_lib

Канала "Заметки репетитора" в telegram: @mentor_it

Наука
7 млн интересуются