Тернарный условный оператор
В компьютерном программировании тернарный условный оператор — это тернарный оператор , который является частью синтаксиса основных условных выражений в нескольких языках программирования . Его обычно называют условным оператором , троичным if или встроенным if (сокращенно iif ). Выражение a ? b : c
оценивается как b
если значение a
верно, а в противном случае c
. Можно прочитать это вслух как «если а, то б, иначе с». Форма a ? b : c
является наиболее распространенным, но существует альтернативный синтаксис; например, Раку использует синтаксис a ?? b !! c
чтобы избежать путаницы с инфиксными операторами ?
и !
, тогда как в Visual Basic .NET он принимает форму If(a, b, c)
.
Первоначально он взят из CPL , в котором эквивалентен синтаксис для e1 ? e2 : e3
был e1 → e2, e3
. [1] [2]
Хотя возможны многие тернарные операторы, условный оператор настолько распространен, а другие тернарные операторы настолько редки, что условный оператор обычно называют тернарным оператором.
Вариации
[ редактировать ]Подробная семантика тернарного оператора, а также его синтаксис существенно различаются от языка к языку.
Отличие верхнего уровня от одного языка к другому заключается в том, допускают ли выражения побочные эффекты (как в большинстве процедурных языков) и обеспечивает ли язык семантику вычисления короткого замыкания , при которой оценивается только выбранное выражение (большинство стандартных операторов в большинстве языков оценивают все аргументы).
Если язык поддерживает выражения с побочными эффектами, но не определяет сокращенное вычисление, то существует дальнейшее различие в отношении того, какое выражение вычисляется первым — если язык гарантирует какой-либо определенный порядок (имейте в виду, что условное выражение также считается выражением).
Более того, если никакой порядок не гарантирован, существует различие в том, классифицируется ли результат как неопределенный (значение, полученное из некоторого порядка) или неопределенный (любое значение вообще по прихоти компилятора перед лицом побочных эффектов или даже авария).
Если язык не допускает побочных эффектов в выражениях (обычно в функциональных языках), то порядок вычисления не имеет семантики значений, хотя он все же может влиять на то, завершается ли бесконечная рекурсия, или иметь другие последствия для производительности (в функциональном языке). выражениям соответствия свойственна короткая оценка, и естественное использование тернарного оператора возникает реже, поэтому этот вопрос вызывает ограниченное беспокойство).
По этим причинам в некоторых языках форма утверждения variable = condition ? expr1 : expr2;
может иметь немного другую семантику, чем условная форма блока if (condition) { variable = expr1; } else { variable = expr2;
} (в языке C (синтаксис приведенного примера) они фактически эквивалентны).
Ассоциативность вложенных тернарных операторов также может различаться от языка к языку. Почти во всех языках тернарный оператор правоассоциативен , так что a == 1 ? "one" : a == 2 ? "two" : "many"
оценивается интуитивно как a == 1 ? "one" : (a == 2 ? "two" : "many")
, но PHP , в частности, известен своей левоассоциативностью, [3] и оценивается следующим образом: (a == 1 ? "one" : a == 2) ? "two" : "many"
, чего редко ожидает любой программист. (В приведенных примерах предполагается, что тернарный оператор имеет низкий приоритет оператора , что справедливо для всех языков семейства C и многих других.)
Эквивалентность карте
[ редактировать ]Тернарный оператор также можно рассматривать как операцию бинарного отображения.
В R — и других языках с кортежами литеральных выражений — можно имитировать тернарный оператор с помощью чего-то вроде выражения R. c(expr1,expr2)[1+condition]
(эта идиома немного более естественна в языках с индексами с нулевым происхождением).
Вложенные тройки можно моделировать как c(expr1,expr2,expr3)[which.first((c(cond1,cond2,TRUE))]
где функция which.first
возвращает индекс первого истинного значения в векторе условий. Обратите внимание, что оба этих эквивалента карты являются бинарными операторами, что показывает, что тернарный оператор является троичным по синтаксису, а не по семантике. Эти конструкции можно рассматривать как слабую форму каррирования , основанную на конкатенации данных, а не на композиции функций.
Если язык предоставляет механизм фьючерсов или промисов , то оценку короткого замыкания иногда можно моделировать в контексте операции с бинарной картой.
Условное присвоение
[ редактировать ]?:
используется следующим образом:
condition ? value_if_true : value_if_false
Условие как оценивается истинное или ложное как логическое выражение . На основе оценки логического условия все выражение возвращает value_if_true, если условие истинно, и value_if_false в противном случае. Обычно два подвыражения value_if_true и value_if_false должны иметь один и тот же тип, который определяет тип всего выражения. Важность этой проверки типов заключается в наиболее распространенном использовании оператора — в операторах условного присваивания . В этом случае оно отображается как выражение в правой части оператора присваивания следующим образом:
variable = condition ? value_if_true : value_if_false
Оператор ?: аналогичен тому, как условные выражения ( конструкции if-then-else ) работают в функционального программирования языках , таких как Scheme , ML , Haskell и XQuery , поскольку if-then-else формирует в них выражение, а не оператор. языки.
Использование
[ редактировать ]Чаще всего условный оператор используется для создания краткого простого оператора условного присваивания. Например, если мы хотим реализовать некоторый код C, чтобы изменить обычные часы работы магазина с 9 часов на 12 часов по воскресеньям, мы можем использовать
int opening_time = (day == SUNDAY) ? 12 : 9;
вместо более многословного
int opening_time;
if (day == SUNDAY)
opening_time = 12;
else
opening_time = 9;
Обе формы почти эквивалентны. Имейте в виду, что ?:
— это выражение, а if-then-else — это оператор. Обратите внимание, что ни части true , ни false не могут быть опущены из условного оператора без отчета об ошибке при синтаксическом анализе. Это контрастирует с операторами if-then-else, где предложение else можно опустить.
Большинству языков, в которых упор делается на функциональное программирование, такой оператор не нужен, поскольку их регулярное условное выражение(я) в первую очередь является выражением, например, Scheme. выражение (if (> a b) a b)
семантически эквивалентно выражению C (a > b) ? a : b
. Это также имеет место во многих императивных языках, начиная с АЛГОЛА , где можно написать result := if a > b then a else b
, или Smalltalk ( result := (a > b) ifTrue: [ a ] ifFalse: [ b ]
) или Рубин ( result = if a > b then a else b end
, хотя result = a > b ? a : b
тоже работает).
Обратите внимание, что некоторые языки могут оценивать как истинное, так и ложное выражение, даже если переменной будет присвоено только одно или другое. Это означает, что если выражение true или false содержит вызов функции, эта функция может быть вызвана и выполнена (вызывая любые связанные побочные эффекты из-за выполнения функции), независимо от того, будет ли использоваться ее результат. Программистам следует ознакомиться со спецификациями своего языка программирования или протестировать тернарный оператор, чтобы определить, будет ли язык оценивать оба выражения таким образом. Если да, и это нежелательное поведение, то оператор if-then-else следует использовать .
Экшнскрипт 3
[ редактировать ]condition ? value_if_true : value_if_false
Есть
[ редактировать ]В версии Ada 2012 года появились условные выражения (с использованием if
и case
), как часть расширенного набора выражений, включая количественные выражения и функции выражений. Обоснование Ады 2012 [4] излагаются мотивы того, что у Ады их не было раньше, а также мотивы их добавления сейчас, например, для поддержки «контрактов» (также новых).
Pay_per_Hour := (if Day = Sunday
then 12.50
else 10.00);
Если значение if_expression само имеет логический тип, то else
часть может быть опущена, значение равно True. Несколько условий могут быть объединены в цепочку с помощью elsif
.
АЛГОЛ 68
[ редактировать ]Оба АЛГОЛа 68 ( предложения выбора if и case ) предоставляют программисту выбор либо « жирного » синтаксиса, либо « краткой » формы.
- Единственное предложение выбора:
if condition then statements [ else statements ] fi "brief" form: ( condition | statements | statements )
- Прикованное предложение выбора :
if condition1 then statements elif condition2 then statements [ else statements ] fi "brief" form: ( condition1 | statements |: condition2 | statements | statements )
АПЛ
[ редактировать ]При использовании следующего синтаксиса вычисляются оба выражения (с value_if_false
сначала оценивается, затем condition
, затем value_if_false
):
result ← value_if_true ⊣⍣ condition ⊢ value_if_false
Этот альтернативный синтаксис обеспечивает короткую оценку:
result ← { condition : expression_if_true ⋄ expression_if_false } ⍬
АВК
[ редактировать ]result = condition ? value_if_true : value_if_false
Баш
[ редактировать ]Настоящий тернарный оператор существует только для арифметических выражений:
((result = condition ? value_if_true : value_if_false))
Для строк существуют только обходные пути, например:
result=$([[ "$a" = "$b" ]] && echo "value_if_true" || echo "value_if_false")
Где "$a" = "$b"
может быть любое состояние [[ … ]]
конструкция может оценить. Вместо [[ … ]]
может быть любая другая команда bash. При успешном выходе выполняется первая команда echo, в противном случае выполняется вторая.
С
[ редактировать ]Традиционная конструкция if-else в C записывается:
if (a > b) {
result = x;
}
else {
result = y;
}
Это можно переписать в виде следующего утверждения:
result = a > b ? x : y;
Как и в конструкции if-else, оценивается только одно из выражений «x» и «y». Это важно, если оценка «x» или «y» имеет побочные эффекты . [5] Поведение не определено, если предпринята попытка использовать результат условного оператора в качестве lvalue . [5]
Расширение GNU для C позволяет опустить второй операнд и неявно использовать первый операнд также как второй:
a = x ? : y;
Выражение эквивалентно
a = x ? x : y;
за исключением того, что выражения a и x вычисляются только один раз. Разница значительна, если оценка выражения имеет побочные эффекты. Эту сокращенную форму иногда называют оператором Элвиса на других языках.
С#
[ редактировать ]В C# , если условие истинно, первое выражение вычисляется и становится результатом; если false, второе выражение оценивается и становится результатом. Как и в Java, всегда оценивается только одно из двух выражений.
// condition ? first_expression : second_expression;
static double sinc(double x)
{
return x != 0.0 ? Math.Sin(x) / x : 1.0;
}
С++
[ редактировать ]В отличие от C , приоритет ?:
Оператор в C++ аналогичен оператору присваивания ( =
или OP=
), и он может возвращать lvalue. [6] Это означает, что выражения типа q ? a : b = c
и (q ? a : b) = c
оба легальны и анализируются по-разному, причем первый эквивалентен q ? a : (b = c)
.
В C++ существуют ситуации условного присваивания, когда использование оператора if-else невозможно, поскольку этот язык явно различает инициализацию и присваивание . В таком случае всегда можно использовать вызов функции, но это может быть громоздко и неэлегантно. Например, чтобы передать условно разные значения в качестве аргумента конструктору поля или базового класса, невозможно использовать простой оператор if-else ; в этом случае мы можем использовать выражение условного присваивания или вызов функции. Имейте в виду также, что некоторые типы допускают инициализацию, но не позволяют присваивание, или даже то, что оператор присваивания и конструктор делают совершенно разные вещи. Последнее справедливо для ссылочных типов, например:
#include <iostream>
#include <fstream>
#include <string>
int main(int argc, char *argv[])
{
std::string name;
std::ofstream fout;
if (argc > 1 && argv[1])
{
name = argv[1];
fout.open(name.c_str(), std::ios::out | std::ios::app);
}
std::ostream &sout = name.empty() ? std::cout : fout;
sout << "Hello, world!\n";
return 0;
}
В этом случае if-else используется оператор if-else. вместо оператора ?:
Оператор заставляет цель присваивания быть объявленной за пределами ветвей как указатель , который можно свободно привязывать к различным объектам.
std::ostream* sout = &fout;
if (name.empty()) {
sout = &std::cout;
}
*sout << "Hello, world!\n";
В этом простом примере sout
указатель может быть инициализирован значением по умолчанию, что снижает риск оставить указатели неинициализированными или нулевыми . Тем не менее, бывают случаи, когда хорошего значения по умолчанию не существует или создание значения по умолчанию обходится дорого. В более общем смысле, отслеживание нулевого указателя увеличивает когнитивную нагрузку. Поэтому возможно только условное присвоение ссылке через ?:
Оператор передает семантику инициализации переменной только одним из двух вариантов на основе соответствующего предиката.
Более того, условный оператор может возвращать lvalue, т.е. значение, которому можно присвоить другое значение. Рассмотрим следующий пример:
#include <iostream>
int main(int argc, char *argv[])
{
int a = 0;
int b = 0;
(argc > 1 ? a : b) = 1;
std::cout << "a: " << a
<< " b: " << b
<< '\n';
return 0;
}
В этом примере, если логическое выражение argc > 1
дает значение true
в строке 8 значение 1
присваивается переменной a
, в противном случае значение 1
присваивается переменной b
.
CFML
[ редактировать ]Пример ?:
оператор в CFML :
result = randRange(0,1) ? "heads" : "tails";
Примерно в 50% случаев randRange()
выражение вернет 1 (истина) или 0 (ложь); это означает, что результат примет значение «орёл» или «решка» соответственно.
Lucee, Railo и ColdFusion 11 специально для
[ редактировать ]Lucee , Railo и ColdFusion 11 также реализуют оператор Элвиса, ?:
который вернет значение выражения, если оно не равно нулю, в противном случае — указанное значение по умолчанию.
Синтаксис:
result = expression ?: value_if_expression_is_null
Пример:
result = f() ?: "default";
// where...
function f(){
if (randRange(0,1)){ // either 0 or 1 (false / true)
return "value";
}
}
writeOutput(result);
Функция f()
вернется value
примерно в 50% случаев, иначе ничего не вернет. Если f()
возвращает «значение», result
примет это значение, в противном случае примет значение «по умолчанию».
Кофескрипт
[ редактировать ]Пример использования этого оператора в CoffeeScript :
if 1 is 2 then "true value" else "false value"
Возвращает «ложное значение».
Общий Лисп
[ редактировать ]Присвоение с использованием условного выражения в Common Lisp :
(setq result (if (> a b) x y))
Альтернативная форма:
(if (> a b)
(setq result x)
(setq result y))
Кристалл
[ редактировать ]Пример использования этого оператора в Crystal :
1 == 2 ? "true value" : "false value"
Возврат "false value"
.
Компилятор Crystal преобразует условные операторы в if
выражения, поэтому приведенное выше семантически идентично:
if 1 == 2
"true value"
else
"false value"
end
Дарт
[ редактировать ]Синтаксис языка программирования Dart и в первую очередь вдохновлен такими языками, как Java, C# и JavaScript, что означает, что принадлежит к семейству C он унаследовал традиционный синтаксис. ?:
синтаксис для его условного выражения.
Пример:
return x.isEven ? x ~/ 2 : x * 3 + 1;
Как и другие условия в Dart, выражение перед ?
должен иметь логическое значение.
Синтаксис Dart использует оба ?
и :
различными другими способами, что вызывает двусмысленность в грамматике языка. Выражение типа:
{ x as T ? [1] : [2] }
может быть проанализирован либо как «литерал набора», содержащий один из двух списков , либо как «литерал карты» {((x as T?)[1]) : [2]}
. В таких ситуациях язык всегда выбирает условное выражение.
У Дарта также есть второй тернарный оператор, []=
оператор, обычно используемый для установки значений в списках или картах, что делает термин «тройной оператор» неоднозначным в контексте Dart.
Дельфи
[ редактировать ]В Дельфи IfThen
функция может использоваться для достижения того же, что и ?:
. Если System.Math
используется библиотека, IfThen
Функция возвращает числовое значение, например Integer , Double или Extended. Если System.StrUtils
используется библиотека, эта функция также может возвращать строковое значение.
С использованием System.Math
function IfThen(AValue: Boolean; const ATrue: Integer; const AFalse: Integer): Integer;
function IfThen(AValue: Boolean; const ATrue: Int64; const AFalse: Int64): Int64;
function IfThen(AValue: Boolean; const ATrue: UInt64; const AFalse: UInt64): UInt64;
function IfThen(AValue: Boolean; const ATrue: Single; const AFalse: Single): Single;
function IfThen(AValue: Boolean; const ATrue: Double; const AFalse: Double): Double;
function IfThen(AValue: Boolean; const ATrue: Extended; const AFalse: Extended): Extended;
Используя System.StrUtils
библиотека
function IfThen(AValue: Boolean; const ATrue: string; AFalse: string = ''): string;
Пример использования:
function GetOpeningTime(Weekday: Integer): Integer;
begin
{ This function will return the opening time for the given weekday: 12 for Sundays, 9 for other days }
Result := IfThen((Weekday = 1) or (Weekday = 7), 12, 9);
end;
Однако, в отличие от истинного тернарного оператора, оба результата оцениваются до выполнения сравнения. Например, если одним из результатов является вызов функции, которая вставляет строку в таблицу базы данных, эта функция будет вызываться независимо от того, выполнено ли условие для возврата этого конкретного результата.
Ф#
[ редактировать ]В F# встроенный синтаксис if-then-else уже является выражением, которое всегда должно возвращать значение.
let num = if x = 10 then 42 else 24
В F# есть особый случай, когда вы можете опустить ветвь else, если возвращаемое значение имеет тип unit. Таким образом, вы можете создавать побочные эффекты без использования ветки else.
if x = 10 then
printfn "It is 10"
Но даже в этом случае выражение if вернет единицу. Вам не нужно писать ветку else, потому что компилятор примет тип модуля else.
ФОРТ
[ редактировать ]Поскольку FORTH — стек-ориентированный язык и любое выражение может оставить значение в стеке, все IF
/ ELSE
/ THEN
последовательности могут генерировать значения:
: test ( n -- n ) 1 AND IF 22 ELSE 42 THEN ;
Это слово принимает в стек 1 параметр, и если это число нечетное, остается 22. Если оно четное, в стеке остается 42.
Фортран
[ редактировать ]С дополнениями к коду в версии 1995 года в компилятор Фортрана был добавлен тернарный оператор как встроенная функция. merge
:
variable = merge(x,y,a>b)
Обратите внимание, что и x, и y оцениваются до того, как из функции будут возвращены результаты того или иного значения. Здесь x возвращается, если условие выполняется, и y в противном случае.
FreeMarker
[ редактировать ]Эта встроенная функция существует начиная с FreeMarker 2.3.20.
Используется как booleanExp?then(whenTrue, whenFalse)
, выполняет ту же роль, что и тернарный оператор в C-подобных языках.
<#assign x = 10>
<#assign y = 20>
<#-- Prints the maximum of x and y: -->
${(x > y)?then(x, y)}
Идти
[ редактировать ]нет троичного оператора if В Go , поэтому всегда требуется использование полного оператора if. [7]
Хаскелл
[ редактировать ]Встроенный синтаксис if-then-else является встроенным: выражение
if predicate then expr1 else expr2
имеет тип
Bool -> a -> a -> a
Базовая библиотека также предоставляет функцию Data.Bool.bool
:
bool :: a -> a -> Bool -> a
В обоих случаях не требуется никакой специальной обработки, чтобы гарантировать, что оценивается только выбранное выражение, поскольку Haskell по умолчанию не является строгим. Это также означает, что можно определить оператор, который при использовании в сочетании с $
оператор, работает точно так же, как ?:
на большинстве языков:
(?) :: Bool -> a -> a -> a
(?) pred x y = if pred then x else y
infix 1 ?
-- example (vehicle will evaluate to "airplane"):
arg = 'A'
vehicle = arg == 'B' ? "boat" $
arg == 'A' ? "airplane" $
arg == 'T' ? "train" $
"car"
Однако более идиоматично использовать защиту шаблонов.
-- example (vehicle will evaluate to "airplane"):
arg = 'A'
vehicle | arg == 'B' = "boat"
| arg == 'A' = "airplane"
| arg == 'T' = "train"
| otherwise = "car"
Ява
[ редактировать ]В Java это выражение оценивается как:
// If foo is selected, assign selected foo to bar. If not, assign baz to bar.
Object bar = foo.isSelected() ? foo : baz;
Обратите внимание, что Java, как и C#, оценивает только используемое выражение и не оценивает неиспользуемое выражение. [8]
Юлия
[ редактировать ]У Юлии : «Обратите внимание, что пространства вокруг ?
и :
обязательны: выражение типа a?b:c
не является допустимым троичным выражением (но допускается перевод строки после обоих ?
и :
)" [9]
JavaScript
[ редактировать ]Условный оператор в JavaScript аналогичен оператору в C++ и Java , за исключением того, что среднее выражение не может быть выражением с запятой. Кроме того, как и в C++, но в отличие от C или Perl , он не будет связываться сильнее, чем присваивание справа от него: q ? a : b = c
эквивалентно q ? a : (b = c)
вместо (q ? a : b) = c
. [10]
var timeout = settings === null ? 1000 : settings.timeout;
Как и в C# и Java, выражение будет оцениваться только тогда и только тогда, когда выражение соответствует заданному условию; другое выражение не будет оцениваться.
Котлин
[ редактировать ]Котлин не включает традиционные ?:
тернарный оператор, однако if
s можно использовать как выражения, которые можно присваивать, [11] достижения тех же результатов. Обратите внимание, что по мере роста сложности условного оператора программист может рассмотреть возможность замены его if
- else
выражение с when
выражение.
val max = if (a > b) a else b
Два
[ редактировать ]В Lua нет традиционного условного оператора. Однако поведение его короткого замыкания and
и or
операторы позволяют эмулировать такое поведение:
-- equivalent to var = cond ? a : b;
var = cond and a or b
Это удастся, если только a
является логически ложным (т. false
или nil
); в этом случае выражение всегда будет иметь результат b
. Если это игнорировать, это может привести к неожиданному поведению.
Можно использовать и другие варианты, но они, как правило, более многословны:
-- parentheses around the table literal are required
var = (
{
[true] = a,
[false] = b
}
)[not not cond]
Луау, диалект Луа, имеет тройные выражения, похожие на операторы if, но, в отличие от них, у них нет end
ключевое слово и else
пункт обязателен. По желанию можно добавить elseif
статьи. Он предназначен для замены cond and a or b
идиома и, как ожидается, будет работать правильно во всех случаях. [12]
-- in Luau
var = if cond then a else b
-- with elseif clause
sign = if var < 0 then -1 elseif var == 0 then 0 else 1
Цель-C
[ редактировать ]состояние ? значение_если_истина: значение_если_ложь
int min = (1 < 2) ? 1 : 2;
Это установит переменную min
к 1
потому что условие (1 < 2)
является true
.
Перл
[ редактировать ]Традиционная конструкция if-else в Perl записывается:
if ($a > $b) {
$result = $x;
} else {
$result = $y;
}
Переписано для использования условного оператора:
$result = $a > $b ? $x : $y;
Приоритет условного оператора в Perl такой же, как в C, а не в C++. Удобно, что он имеет более высокий приоритет, чем оператор запятой , но ниже, чем приоритет большинства операторов, используемых в выражениях внутри тернарного оператора, поэтому использование круглых скобок требуется редко. [13]
Его ассоциативность соответствует ассоциативности C и C++, а не PHP. В отличие от C, но как и C++, Perl позволяет использовать условное выражение в качестве L-значения ; [14] например:
$a > $b ? $x : $y = $result;
назначу $result
либо $x
или $y
в зависимости от логического результата логического выражения.
Соответствующие правила приоритета и ассоциативность используемых операторов гарантируют, что версия без каких-либо круглых скобок эквивалентна этой явно заключенной в круглые скобки версии:
(($a > $b) ? $x : $y) = $result;
Это эквивалентно версии if-else:
if ($a > $b) {
$x = $result;
} else {
$y = $result;
}
PHP
[ редактировать ]Простая реализация PHP такова:
$abs = $value >= 0 ? $value : -$value;
В отличие от большинства других языков программирования, условный оператор в PHP является левоассоциативным, а не правоассоциативным. задано значение T Таким образом, если для arg , PHP-код в следующем примере выдаст значение «horse» вместо «train» , как можно было бы ожидать: [15]
<?php
$arg = "T";
$vehicle = ( ( $arg == 'B' ) ? 'bus' :
( $arg == 'A' ) ? 'airplane' :
( $arg == 'T' ) ? 'train' :
( $arg == 'C' ) ? 'car' :
( $arg == 'H' ) ? 'horse' :
'feet' );
echo $vehicle;
Причина в том, что вложение двух условных операторов создает условие слишком большого размера, в котором последние два параметра являются его ветвями: c1 ? o1 : c2 ? o2 : o3
действительно ((c1 ? o1 : c2) ? o2 : o3)
. Это признано [16] и, вероятно, не изменится. [17] Чтобы избежать этого, необходимы вложенные круглые скобки, как в этом примере:
<?php
$arg = "T";
$vehicle = $arg == "B" ? "bus" :
($arg == "A" ? "airplane" :
($arg == "T" ? "train" :
($arg == "C" ? "car" :
($arg == "H" ? "horse" :
"feet"))));
echo $vehicle;
Это приведет к выводу поезда на выходные данные, аналогично правильному ассоциативному условному оператору.
Питон
[ редактировать ]Хотя его реализация была отложена на несколько лет из-за разногласий по поводу синтаксиса, оператор для условного выражения в Python был одобрен как предложение расширения Python 308 и добавлен в версию 2.5 в сентябре 2006 года. Условный оператор Python отличается от обычного ?:
оператор в порядке его операндов. Общая форма: [18]
result = x if a > b else y
Эта форма предлагает рассмотреть x
как нормальное значение и y
как исключительный случай.
До Python 2.5 существовало несколько способов аппроксимации условного оператора (например, путем индексации в массив из двух элементов), каждый из которых имел недостатки по сравнению со встроенным оператором.
Р
[ редактировать ]Традиционная конструкция if-else в R (которая является реализацией S ):
if (a < b) {
x <- "true"
} else {
x <- "false"
}
Если в каждом блоке только один оператор, фигурные скобки можно опустить, как в C :
if (a < b)
x <- "true"
else
x <- "false"
Приведенный выше код можно записать следующим нестандартным сокращенным способом:
x <- if (a < b) "true" else "false"
Существует также функция ifelse
это позволяет переписать приведенное выше выражение как:
x <- ifelse(a < b, "true", "false")
The ifelse
функция автоматически векторизуется. Например:
> ifelse(c (0, 2) < 1, "true", "false")
[1] "true" "false"
Раку
[ редактировать ]Раку использует удвоенный ??
символ вместо одиночного ?
и двойной !!
символ вместо :
[19]
$result = $a > $b ?? $x !! $y;
Руби
[ редактировать ]Пример использования этого оператора в Ruby :
1 == 2 ? "true value" : "false value"
Возвращает «ложное значение».
Традиционная конструкция if-else в Ruby записывается: [20]
if a > b
result = x
else
result = y
end
Это также можно записать как:
result = if a > b
x
else
y
end
Их можно переписать в виде следующего утверждения:
result = a > b ? x : y
Ржавчина
[ редактировать ]Будучи языком программирования, ориентированным на выражения , Rust существует if expr1 else expr2
синтаксис может вести себя как традиционный ?:
тернарный оператор делает. Более ранние версии языка имели ?:
оператор, но его удалили [21] из-за дублирования с if
. [22]
Обратите внимание на отсутствие точек с запятой в приведенном ниже коде по сравнению с более декларативным кодом. if
... else
блок и точка с запятой в конце присваивания y
.
let x = 5;
let y = if x == 5 {
10
} else {
15
};
Это также можно записать как:
let y = if x == 5 { 10 } else { 15 };
Обратите внимание, что фигурные скобки обязательны в условных выражениях Rust.
Вы также можете использовать match
выражение:
let y = match x {
5 => 10,
_ => 15,
};
Схема
[ редактировать ]То же, что и в Common Lisp. Каждое выражение имеет значение. Таким образом, встроенный if
можно использовать:
(let* ((x 5)
(y (if (= x 5) 10 15)))
...)
Смолток
[ редактировать ]Каждое выражение (отправка сообщения) имеет значение. Таким образом ifTrue:ifFalse:
можно использовать:
|x y|
x := 5.
y := (x == 5) ifTrue:[10] ifFalse:[15].
SQL
[ редактировать ]SQL CASE
выражение является обобщением тернарного оператора. Вместо одного условия и двух результатов n условий и n+1 можно указать результатов.
С одним условием он эквивалентен (хотя и более многословен) тернарному оператору:
SELECT (CASE WHEN a > b THEN x ELSE y END) AS CONDITIONAL_EXAMPLE
FROM tab;
Это можно расширить до нескольких условных операторов:
SELECT (CASE WHEN a > b THEN x WHEN a < b THEN y ELSE z END) AS CONDITIONAL_EXAMPLE
FROM tab;
MySQL
[ редактировать ]В дополнение к стандартному CASE
выражения, MySQL предоставляет IF
функционировать как расширение:
IF(cond, a, b);
SQL-сервер
[ редактировать ]В дополнение к стандартному CASE
выражения, SQL Server (с 2012 г.) предоставляет IIF
функция:
IIF(condition, true_value, false_value)
Oracle SQL
[ редактировать ]В дополнение к стандартному CASE
выражения, Oracle имеет функциональный аналог с переменным числом аргументов, который работает аналогично оператору переключения и может использоваться для эмуляции условного оператора при проверке на равенство.
-- General syntax takes case-result pairs, comparing against an expression, followed by a fall-back result:
DECODE(expression, case1, result1,
...
caseN, resultN,
resultElse)
-- We can emulate the conditional operator by just selecting one case:
DECODE(expression, condition, true, false)
The DECODE
функция сегодня устарела в пользу стандартной CASE
выражение. Это можно использовать как в запросах Oracle SQL, так и в PL/SQL , тогда как блоках decode
можно использовать только в первом случае.
Быстрый
[ редактировать ]Тернарный условный оператор Swift написан обычным способом, принятым в языке C, и используется внутри выражений.
let result = a > b ? a : b
Ткл
[ редактировать ]В Tcl этот оператор доступен в expr
только выражения:
set x 5
set y [expr {$x == 5 ? 10 : 15}]
За пределами expr
, if
может использоваться для аналогичной цели, поскольку он также возвращает значение:
package require math
set x 5
set y [if {$x == 5} {
::math::random $x
} else {
::math::fibonacci $x
}]
Испытательный Стенд
[ редактировать ]Если в выражении National Instruments TestStand условие истинно, первое выражение вычисляется и становится результатом условной операции; если false, второе выражение оценивается и становится результатом. Всегда оценивается только одно из двух выражений.
condition ? first_expression : second_expression
Например:
RunState.Root.Parameters.TestSocket.Index == 3 ? Locals.UUTIndex = 3 : Locals.UUTIndex = 0
Устанавливает UUTIndex
локальная переменная равна 3, если TestSocket.Index
равно 3, в противном случае он устанавливает UUTIndex
до 0.
Как и в других языках, first_expression и Second_expression не обязательно должны быть автономными выражениями, что позволяет использовать оператор для присвоения переменных:
Locals.UUTIndex = ( RunState.Root.Parameters.TestSocket.Index == 3 ? 3 : 0 )
Верилог
[ редактировать ]Verilog технически является языком описания аппаратного обеспечения , а не языком программирования, хотя семантика обоих очень похожа. Он использует ?:
синтаксис тернарного оператора.
// using blocking assignment
wire out;
assign out = sel ? a : b;
Это эквивалентно более подробному коду Verilog:
// using blocking assignment
wire out;
if (sel === 1) // sel is 1, not 0, x or z
assign out = a;
else if (sel === 0) // sel is 0, x or z (1 checked above)
assign out = b;
else // sel is x or z (0 and 1 checked above)
assign out = [comment]; // a and b are compared bit by bit, and return for each bit
// an x if bits are different, and the bit value if the same
Визуальный Бейсик
[ редактировать ]Visual Basic не использует ?:
как таковой, но имеет очень похожую реализацию этого сокращения if...else
заявление. Используя первый пример, представленный в этой статье, он может:
' variable = IIf(condition, value_if_true, value_if_false)
Dim opening_time As Integer = IIf((day = SUNDAY), 12, 9)
В приведенном выше примере IIf
является тернарной функцией, но не тернарным оператором. Как функция, значения всех трех частей оцениваются до того, как произойдет вызов функции. Это наложило ограничения, и в Visual Basic .Net 9.0, выпущенном вместе с Visual Studio 2008, был введен настоящий условный оператор с использованием If
ключевое слово вместо IIf
. Это позволяет работать следующему примеру кода:
Dim name As String = If(person Is Nothing, "", person.Name)
С использованием IIf
, person.Name
будет оценено, даже если человек null
(Ничего), вызывая исключение . С настоящим условным оператором короткого замыкания, person.Name
не оценивается, если человек не null
.
В Visual Basic версии 9 добавлен оператор If()
в дополнение к существующему IIf()
функция, существовавшая ранее. Будучи настоящим оператором, он не имеет побочных эффектов и потенциальной неэффективности, присущих обычному оператору. IIf()
функция.
Синтаксис токенов аналогичен: If([condition], op1, op2)
против IIf(condition, op1, op2)
. Как упоминалось выше, вызов функции имеет существенные недостатки, поскольку все подвыражения должны быть вычислены в соответствии со стратегией оценки Visual Basic для вызовов функций, и результат всегда будет иметь вариант типа (VB) или объект (VB.NET). If()
однако оператор не страдает от этих проблем, поскольку поддерживает условную оценку и определяет тип выражения на основе типов его операндов.
Зиг
[ редактировать ]Зиг использует выражения if-else вместо тернарного условного оператора: [23]
const result = if (a != b) 47 else 3089;
Тип результата
[ редактировать ]Очевидно, что тип результата ?:
Оператор должен быть в некотором смысле унификацией типов его второго и третьего операндов. это достигается В C для числовых типов путем арифметического продвижения ; поскольку в C нет иерархии типов для типов указателей , операнды указателей могут использоваться только в том случае, если они имеют один и тот же тип (игнорируя квалификаторы типа ) или один из них имеет значение void или NULL . является неопределенным Совмещение указателей и целочисленных или несовместимых типов указателей ; таким образом
number = spell_out_numbers ? "forty-two" : 42;
приведет к ошибке времени компиляции в большинстве компиляторов.
?: в рекомендациях по стилю
[ редактировать ]Условные операторы широко используются и могут быть полезны в определенных обстоятельствах, чтобы избежать использования if
утверждение, либо потому, что дополнительное словоблудие было бы слишком длинным, либо потому, что синтаксический контекст не позволяет использовать утверждение. Например:
#define MAX(a, b) (((a)>(b)) ? (a) : (b))
или
for (i = 0; i < MAX_PATTERNS; i++)
c_patterns[i].ShowWindow(m_data.fOn[i] ? SW_SHOW : SW_HIDE);
(Последний пример использует Microsoft Foundation Classes Framework для Win32 .)
Инициализация
[ редактировать ]Важным применением условного оператора является возможность использования одного оператора инициализации вместо нескольких операторов инициализации. Во многих случаях это также допускает однократное присвоение и возможность использования идентификатора в качестве константы .
Самое простое преимущество — избежать дублирования имени переменной, как в Python:
x = 'foo' if b else 'bar'
вместо:
if b:
x = 'foo'
else:
x = 'bar'
Что еще более важно, в языках с областью действия блока , таких как C++, блоки оператора if/else создают новые области видимости, и поэтому переменные должны быть объявлены перед оператором if/else, как:
std::string s;
if (b)
s = "foo";
else
s = "bar";
Использование условного оператора упрощает это:
std::string s = b ? "foo" : "bar";
Более того, поскольку инициализация теперь является частью объявления, а не отдельным оператором, идентификатор может быть константой (формально const
тип):
const std::string s = b ? "foo" : "bar";
Селекторы случаев
[ редактировать ]При правильном форматировании условный оператор можно использовать для написания простых и связных селекторов регистра. Например:
vehicle = arg == 'B' ? bus :
arg == 'A' ? airplane :
arg == 'T' ? train :
arg == 'C' ? car :
arg == 'H' ? horse :
feet;
Соответствующее использование условного оператора в контексте присваивания переменной снижает вероятность ошибки из-за ошибочного присваивания, поскольку присвоенная переменная указывается только один раз, а не несколько раз.
Языки программирования без условного оператора
[ редактировать ]Ниже приведены примеры известных языков программирования общего назначения, в которых нет условного оператора:
- Кофескрипт
- Go Язык программирования [7] (хотя и предоставляется сторонними библиотеками [24] )
- МАТЛАБ
- Pascal, хотя в Object Pascal/Delphi есть функция
IfThen
сделать то же самое (с оговорками) - Ржавчина
if..else
Конструкция является выражением и может использоваться для получения той же функциональности. [25] - Скала
- XProfane
- PowerShell (в старых версиях) — элегантный обходной путь — использовать
(<value for true>,<value for false>)[!(<condition>)]
[26]
См. также
[ редактировать ]- IIf , встроенная функция if
- Нулевой оператор объединения ,
??
оператор - Оператор Элвиса ,
?:
, или иногда?.
, как сокращенный бинарный оператор - Условная дизъюнкция , эквивалентная троичная логическая связка.
- Мультиплексор
Ссылки
[ редактировать ]- ^ Стрейчи, Кристофер (2000). « Основные понятия языков программирования ». Вычисления высшего порядка и символьные вычисления . 13 :11–49. дои : 10.1023/А:1010000313106 . S2CID 14124601 .
- ^ «5.5 Условные выражения». Справочное руководство BCPL (PDF) . 1967. стр. 16–17. Архивировано из оригинала (PDF) 16 марта 2016 г. Проверено 15 марта 2017 г.
- ^ Вастл, Эрик. «Тернарная операторная ассоциативность» . phpsadness.com . PHP-грусть . Проверено 20 сентября 2017 г.
- ^ «Обоснование Ады 2012» . АСАА . Проверено 10 декабря 2015 г.
- ↑ Перейти обратно: Перейти обратно: а б ИСО.МЭК 9899:1999 (Е) 6.5.15.4
- ^ «Приоритет операторов C++» . ru.cppreference.com . раздел: «Заметки».
- ↑ Перейти обратно: Перейти обратно: а б «Есть ли в Go оператор ?:?» . Часто задаваемые вопросы по языку программирования Go . Проверено 5 августа 2012 г.
- ^ Спецификация Java 7: 15.25 Условный оператор? :
- ^ «Поток управления · Язык Джулии» . docs.julialang.org . Проверено 12 марта 2020 г.
- ^ «ECMA-262 Редакция 5.1» . Спецификация языка Ecma . Экма Интернешнл . Проверено 7 сентября 2013 г.
- ^ «Kotlin Lang If Expression» . kotlinlang.org . Проверено 25 апреля 2021 г.
- ^ «Синтаксис § Выражения «если-то-иначе»» . Луау . Проверено 7 февраля 2023 г.
- ^ Кристиансен, Том ; Уолл, Ларри ; Фой, Брайан Д. (февраль 2012 г.). «Глава 2 Унарные и бинарные операторы: Условный оператор». Программирование на Perl (Четвертое изд.). Севастополь, Калифорния: O'Reilly Media . п. 123. ИСБН 978-0-596-00492-7 .
- ^ Уолл, Ларри . «perlop: условный оператор» . Документация по программированию на Perl . Проверено 26 января 2019 г.
- ^ Иви (9 апреля 2012 г.). «PHP: фрактал плохого дизайна» . Проверено 4 октября 2015 г.
- ^ «Операторы сравнения, пример №3: неочевидное троичное поведение» . PHP-сайт . Проверено 26 апреля 2013 г.
- ^ «Ошибка PHP № 61915: неверная ассоциативность тернарного оператора» . PHP-сайт. 02 мая 2012 г. Проверено 26 апреля 2013 г.
Мы не можем это исправить, не нарушив код.
- ^ «Справочник по языку Python» .
- ^ Уолл, Ларри . «Операторы Perl6» . Архивировано из оригинала 29 марта 2009 г. Проверено 18 мая 2010 г.
- ^ Программирование Ruby: условное выполнение
- ^ «Удалить троичный оператор от pwoolcoc · Запрос на включение № 1705 · ржавчина-lang/Rust» . Гитхаб .
- ^ «Удалить тройной оператор · Проблема № 1698 · ржавчина-lang/Rust» . Гитхаб .
- ^ «Справочник по языку Зиг» . ziglan.org . Проверено 9 августа 2023 г.
- ^ «пакет lo — github.com/samber/lo — Пакеты Go» . pkg.go.dev . Проверено 30 сентября 2023 г.
- ^ «Если выражения» . Справочник по ржавчине . Проверено 21 июля 2015 г.
- ^ «Трнарный оператор в PowerShell» . Переполнение стека . Проверено 9 октября 2018 г.