Ternär villkorlig operation (från latin ternarius - "trippel") är en operation implementerad i många programmeringsspråk som returnerar sin andra eller tredje operande beroende på värdet på det logiska uttrycket som ges av den första operanden. En analog till den ternära villkorliga operationen i matematisk logik och boolesk algebra är den villkorliga disjunktionen , som skrivs i formen och implementerar algoritmen: "om , då , annars ".
Vanligtvis är den ternära villkorliga operatorn associerad med operatorn som ?:används i C-liknande programmeringsspråk. Faktum är att liknande operationer med en annan syntax finns i många programmeringsspråk som är långt ifrån C i syntax . Populära språk som har den ternära villkorliga operatorn inbyggd i sin syntax är C , C++ , JavaScript , Objective-C , C# , D , Java , ECMAScript , Perl , PHP , Python , Tcl , Ruby , Verilog , Turbo Basic . Denna operation är skyldig sitt utseende direkt i den ternära infixformen till Algol-60- språket , där det hade en syntax , och sedan till BCPL- språket ( ) [1] istället för det nu bekanta . Prototypen för denna operation är i sin tur en villkorlig funktion av Lisp-språket , skrivet enligt reglerna för Lisp i prefixform och har ett godtyckligt antal argument. if o1 then o2 else o3o1 -> o2, o3o1 ? o2 : o3cond
Vanligtvis inkluderar implementeringen av operationen beräkningen av villkoret och endast ett av uttrycken, vilket i vissa fall ger utökade möjligheter, till exempel anses uttrycket x > 0 ? 0 : sqrt(x)vara korrekt, trots att roten inte är hämtad från negativa tal.
Minsta antal a och b:
min = (a < b) ? a : bKan användas i en icke-uppdragssituation:
sprintf ( titel , "%s %s" , tv_system == TV_PAL ? PAL : SECAM , tv_ingång ? Tv_Name [ tv_ingång - 1 ] : "TESTA" );- i detta fall skulle motsvarande konstruktion med if-then-else kräva att funktionsanropet skrivs sprintffyra gånger.
Basic C har ingen boolesk datatyp ( C99 introducerade den booleska _Bool-typen), så den första operanden måste vara ett tal ( heltal eller reellt ) eller en pekare [2] ; först beräknas dess värde och jämförs med noll , och om det inte är lika med noll, beräknas den andra operanden och returneras, i händelse av likhet - den tredje. Den andra och tredje operanden kan vara av olika typer (inklusive void ).
I C++ har den ternära villkorliga operatorn samma syntax som i C [3] , men på grund av skillnaden mellan initialisering och tilldelning finns det situationer då operationen ?:inte kan ersättas av en konstruktion if-then-else, som till exempel i följande fall:
#include <iostream> #inkludera <fstream> #inkludera <sträng> använder namnutrymme std ; int main ( int argc , char ** argv ) { strängnamn ; _ utströms fout ; if ( argc > 1 && argv [ 1 ]) { namn = argv [ 1 ]; fout . öppna ( namn.c_str ( ), ios :: ut | ios :: app ) ; } ostream & sout = namn . tom () ? cout : fout ; returnera 0 ; }Här initieras variabeln i det ögonblick resultatet av den ternära operationen deklareras. soutEn liknande effekt kunde inte uppnås genom ett enkelt uppdrag i ett eller annat fall.
Dessutom kan den ternära villkorliga operatorn tillämpas på vänster sida av en tilldelningssats:
#include <iostream> int main () { int a = 0 , b = 0 ; const bool cond = ...; ( förutsättning a : b ) = 1 ; _ std :: cout << "a=" << a << ',' << "b=" << b << '\n' ; }I det här exemplet, om den booleska variabeln cond på rad 5 innehåller värdet true, kommer värdet 1 att tilldelas variabel a, annars kommer det att tilldelas variabel b.
I C# har den ternära operatören ytterligare begränsningar relaterade till typsäkerhet. Uttryck 1 och 2 måste vara av samma typ. Detta resulterar i följande:
int a = 1 ; dubbel b = 0,0 ; int nMax = ( a > b ) ? a : b ;Sådan källkod kommer inte att kompileras trots att nMax kommer att bli en . Eftersom a och b måste vara av samma typ, kommer a att befordras till dubbel för att matcha b . Typen av det resulterande värdet för den ternära operationen är dubbelt, och denna typ måste nedkastas till int vid tilldelning: [4]
int a = 1 ; dubbel b = 0,0 ; int nMax ; // Du kan göra så här: nMax = ( int ) (( a > b ) ? a : b ) ; // ...eller så nMax = ( a > b ) ? a : ( int ) b ;Python använder sökordssyntaxif-else :
a = 42 b = 41 resultat = a om a > b annars b hävda resultat == 42Det kan också implementeras via en lista:
[ < uttryck 1 > , < uttryck 2 > ][ < villkor > ]- resultatet av uttryck 1 kommer att returneras om villkoret är falskt; och uttryck 2 om villkoret är sant. Om villkoret inte är ett booleskt uttryck är det möjligt att fylla listan över med ett undantag.
PHP använder en C -liknande syntax:
$a = $b == 1 ? "första värdet" : ( $b == 2 ? "andra värde" : ( $b == 3 ? "resultatvärde" : "standardvärde" ));Den ternära operatorn i PHP motsvarar den längre if-else-konstruktionen. Följande två exempel är likvärdiga:
//Första exemplet $result = isset ( $a ) ? $a : 'DefaultValue' ; //Andra exemplet if ( isset ( $a )) { $result = $a ; } else { $result = 'DefaultValue' ; }Sådana konstruktioner används ofta för att initiera en variabel ändå för efterföljande beräkningar (annars kommer PHP att ge ett E_NOTICE-nivåfel).
Från och med version 5.3 blev det möjligt att inte specificera den andra parametern för operationen. Till exempel är följande två poster likvärdiga:
$Variable = $_GET [ 'Parameter' ] ? $_GET [ 'Parameter' ] : 'DefaultValue' ; $Variable = $_GET [ 'Parameter' ] ?: 'DefaultValue' ;I den klassiska versionen av Visual Basic finns den ternära operatorn som en funktion IIf(Expr, TruePart, FalsePart). Den här funktionen har en funktion: när uttrycket utvärderas Expr, beräknas också TruePartoch FalsePart, oavsett resultatet av uttrycket: sant eller falskt. Detta kan leda till oväntade resultat, och ibland till långsam kodexekvering, om returvärdena är anrop till funktioner med långa operationer.
Dim iCount As Long Public Sub Main () iCount = 1 MsgBox IIf ( 1 = 1 , FuncYes , FuncNo ) Variabeln iCount kommer att innehålla "3" eftersom båda funktionerna kommer att köras MsgBox iCount End Sub Offentlig funktion FuncYes () Som sträng iCount = iCount + 1 FuncYes = "Ja " Slutfunktion Offentlig funktion FuncNo () Som sträng iCount = iCount + 1 FuncNo = "Nej " SlutfunktionFör att ersätta en funktion IIfkan du skriva om uttrycket på en rad, men detta kommer inte att vara en analog till funktionen, utan bara en kort form av grenoperatorn
If Expr Then TruePart Else FalsePartMed tillkomsten av VB.NET ingick den välbekanta ternära operatorn i språkets syntax och skrivs som If(Expr, TruePart, FalsePart). Denna operatör använder reducerade beräkningar, till skillnad från funktionen IIf, som också är tillgänglig för utvecklaren för kompatibilitet med tidigare versioner. [5]
I konfigurationsspråket för 1C:Enterprise-plattformen har den ternära operatören syntaxen:
?(booleskt uttryck, uttryck 1, uttryck 2)Används ofta som en stenografi för konstruktioner Если <логическое выражение> Тогда ... Иначе ... КонецЕсли
I plattformsversion 7.7 var det möjligt att använda en ternär operatör på höger sida om en uppdragsoperatör [6] .
I Haskell är if-grenoperatorn ett villkorligt uttryck: else-uttrycket krävs och måste vara av samma typ som det dåvarande uttrycket. Även i standardbiblioteket Data.Bool [7] finns en bool-funktion som returnerar ett av två uttryck beroende på predikatets värde.
En ternär operation i sin vanliga form kan definieras som en infixfunktion via mönstermatchning (typer är valfria):
( ? ) :: Bool -> a -> a -> a ( ? ) Sant a _ = a ( ? ) Falskt _ b = beller genom någon förgrening, till exempel om eller fall av:
( ? ) predikat thenExpr elseExpr = om predikat then thenExpr else elseExpr ( ? ) predikat thenExpr elseExpr = kasuspredikat för { True - > thenExpr ; _ -> elseExpr }Eftersom (?) är en infix-funktion (binär), tar den de två första argumenten och returnerar en funktion av ett argument. För att tillämpa det på det tredje argumentet används applikationen ($):
sant ? "då" $ "annat" > "då" Falskt ? "då" $ "annat" > "annat"