Uvjetna naredba
U računarstvu, uvjetne naredbe, uvjetni izrazi i uvjetni konstrukti su svojstva programskog jezika koja obavljaju različita računanja ili akcije ovisno o tome evaluira li uvjet koji programer specificira na istinu ili laž (v. bulovski tip podataka). Osim u slučaju predviđanja grananja, ovo se uvijek ostvaruje selektivnim mijenjanjem toka upravljanja ovisno o nekom uvjetu.
U imperativnim programskim jezicima se obično rabi naziv "uvjetna naredba", dok se u funkcijskom programiranju preferiraju nazivi "uvjetni izraz" ili "uvjetni konstrukt", s obzirom na to da svi ovi nazivi imaju različita značenja.
Iako se dinamičko otpremanje obično ne klasificira kao uvjetni konstrukt, ono predstavlja još jedan način odabira među alternativama za vremena izvođenja.
if-then konstrukt (ponekad zvan i kao if-then-else) je uobičajen u mnogim programskim jezicima. Iako sintaksa poprilično varira od jezika do jezika, osnovna struktura (u pseudokodu) izgleda ovako:
If (uvjet) Then
(naredbe)
Else
(naredbe)
End If
Kad interpreter pronađe If, očekuje bulovski uvjet - primjerice, x > 0, što znači "varijabla x sadrži broj koji je veći od nule" - i evaluira taj uvjet. Ako je uvjet istinit, blok naredbi nakon then-a se izvršuje. Inače se izvršavanje nastavlja u sljedećem bloku - bilo u Else bloku (koji je obično opcionalan), ili ako nema "Else" bloka, izvršuju se naredbe nakon End If.
Nakon što su izvršeni bilo blok nakon Then bilo blok nakon Else, upravljanje se vraća na točku nakon End If.
U ranim programskim jezicima - napose u dijalektima BASIC-a 1980-ih - if-then naredba je mogla sadržavati samo GOTO naredbu. Ovo je vodilo ka teško čitljivom programerskom stilu poznatom kao špageti programiranje. Kao posljedica se toga iznjedrilo strukturirano programiranje, koje dopušta ubacivanje unutar if naredbi (praktički) proizvoljne naredbe, i koje se populariziralo do te mjere da je postalo norma.
Korištenjem Else If naredbi moguće je kombinirati nekoliko uvjeta. Izvršuju se samo naredbe koje slijede prvi uvjet za koji se ustanovi istinitost, dok se sve druge preskaču. Naredbe nakon konačnog Else se izvršuju ako nijedan od uvjeta nije istinit. Sljedeći je primjer napisan u programskom jeziku Ada:
'''if''' ''uvjet'' '''then'''
''naredbe'';
'''elseif''' ''uvjet'' '''then'''
''još naredbi'';
'''elseif''' ''uvjet'' '''then'''
''još naredbi'';
...
'''else''' ''uvjet'' '''then'''
''druge naredbe'';
'''end''' '''if''';
elseif je u Adi jednostavno sintaksni šećer za else nakon kojeg slijedi if. U Adi, razlika je u tome što je potrebno samo jedno end if, ako se rabi elseif mjesto else nakon kojeg slijedi if.
U nekim drugim jezicima, kao što je C, else if doslovno znači else nakon kojeg slijedi if - stoga nije potreban niti se pruža ikakav sintaksni šećer.
Mnogi jezici podržavaju if izraze, slične if naredbama, s tim da vraćaju vrijednost kao rezultat. Stoga su istiniski izrazi (koji evaluiraju na vrijednost), ne naredbe (koje samo obavljaju akciju).
U C-u i C-nalik jezicima uvjetni izrazi poprimaju oblik ternarnog operatora zvanog operator uvjetnog izraza, ?:, koji slijedi sljedeći predložak:
(uvjet)?(evaluiraj ako je uvjet istinit):(evaluiraj ako je uvjet lažan)
Ovo znači da uvjeti mogu biti svedeni na jednu liniju koda izraza, za razliku od naredbi, koje su ovdje prikazane u sintaksi C-a:
// Valjano
moja_varijabla = if(x > 10) { "foo" } else { "bar" };
// Nevaljano
moja_varijabla = (x > 10)?"foo":"bar";
Kako bi se ista kao s drugom (valjanom) linijom gore ostvarila rabeći standardnu if/else naredbu, trebalo bi više od jedne linije koda (rabeći standardnu konvenciju o razlamanju koda):
if (x > 10) {
moja_varijabla = 'foo';
}
else {
moja_varijabla = 'bar';
}
U Visual Basicu i nekim drugim jezicima je dana funkcija IIf koja se može rabiti kao uvjetni izraz. Međutim, ona se ne ponaša kao istinski uvjetni izraz, s obzirom na to da su uvijek evaluirane i grane za istinu i laž - radi se samo o tome da je rezultat jedne od njih odbačen, dok je rezultat druge vraćen od strane IIf funkcije.
U Haskellu 98 postoji samo jedan if izraz, ne if naredba, i else dio je obavezan.[1]
Fortran 77 ima "aritmetičku if" naredbu koja je napola između izračunatog IF i case naredbe, zasnovana na trihotomiji , , :
IF (iz) labela1, labela2, labela3
Pri čemu je iz bilo koji numerički izraz (ne nužno cjelobrojni) - ovo je ekvivalentno sa:
IF (iz < 0) GOTO labela1
IF (iz = 0) GOTO labela2
IF (iz > 0) GOTO labela3
S obzirom na to da je ovaj aritmetički IF istovjetan višestrukim GOTO naredbama, smatra s nestruktuiranom naredbom upravljanja, i ne bi se smio rabiti u slučaju dostupnosti struktuiranijih naredbi. U praksi se uočio uporabni obrazac u kojem je većina aritmetičkih IF naredbi referencirala sljedeću naredbu jednom ili dvjema labelama.
Ovo je bila jedina naredba uvjetnog upravljanja u izvornoj implementaciji Fortrana na računalu IBM 704. Na tom je računalu mogla biti implementirana poprilično učinkovito instrukcijama poput 'granaj ako je akumulator negativan'.
Kao suprotnost s drugim jezicima, u Smalltalku uvjetna naredba nije jezični konstrukt već je definirana kao apstraktna metoda u klasi Boolean kao metoda koja prima dva parametra, oba kao zatvorenosti. Boolean ima dvije potklase, True i False, oboje od kojih definiraju metodu, pri čemu True izvršuje samo prvu zatvorenost, False samo drugu.
var := uvjet
ifTrue: [ 'foo' ]
ifFalse: [ 'bar' ]
Switch naredbe (u nekim jezicima, case naredbe) uspoređuju danu vrijednost sa specificiranim konstantama i poduzimaju odgovarajuću akciju ovisno o prvoj sparujućoj konstanti. Primjer slijeva je napisan u Pascalu, dok je primjer zdesna napisan u C-u.
'''case''' nekiZnak '''of''' '''switch''' (nekiZnak) {
'a': akcijaAkoA; '''case''' 'a': akcijaAkoA;
'x': akcijaAkoX; break;
'y','z':AkcijaAkoYiZ; '''case''' 'x': akcijaAkoX;
'''end'''; break;
'''case''' 'y':
'''case''' 'z': AkcijaAkoYiZ;
break;
'''default''': akcijAkoNemaSparivanja;
}
Sparivanje uzoraka je sofisticirana alternativa i if-then-elseif i jednostavnim gorespomenutim case ili switch naredbama. Dostupno je u nekim programskim jezicima poput onih iz ML porodice. Slijedi jednostavan primjer napisan u O'Caml jeziku:
'''match''' voće '''with'''
'''|''' "jabuka" '''->''' skuhaj pitu
'''|''' "ananas" '''->''' napravi frape
'''|''' "banana" '''->''' miješaj''';;'''
Istinska moć sparivanja uzoraka, međutim, leži u mogućnosti konciznog (a) sparivanja nad uzorcima podatkovnih struktura i (b) istovremenog vezanja varijabli. Slijedi primjer napisan u Haskellu koji osvjetljuje oba navedena svojstva:
map _ [] '''=''' []
map f (h : t) '''=''' f h : map f t
Ovaj kod definira poznatu funkciju map, koja primijenjuje prvi argument (funkciju) na svaki od elemenata drugog argumenta (liste), i vraća rezultirajuću listu. Dvije linije koda nisu odvojene definicije funkcije, već se mjesto toga radi o definiciji funkcije u dva slučaja - prvi u slučaju prazne liste (pri čemu funkcija vraća praznu listu), drugi u slučaju neprazne liste.
Sparivanje uzoraka nije strogo govoreći uvijek izborni konstrukt, s obzirom na to da je u Haskellu dopušteno napisati samo jednu alternativu, koja će uvijek biti sparena - u ovoj situaciji se ne rabi kao izborni konstrukt, već jednostavno kao način vezanja varijabli. Međutim, često se rabi kao izborni konstrukt u jezicima u kojima je dostupan.
U asemblerskom jeziku, predviđanje grananja je svojstvo instrukcijskih skupova pojedinih CPU-ova koje dopušta uvjetno izvođenje instrukcija bez nužnog obavljanja skupih uvjetnih skokova.
Ova tablica pruža pregled najrecentnih specifikacija svakog od navedenih jezika. Za jezike za koje ne postoji specifikacija, referira se na najnoviju službeno puštenu implementaciju.
Programski jezik | Struktuirano if | Izbor konstanti | Aritmetičko if | Sparivanje uzoraka[1] | ||
---|---|---|---|---|---|---|
then | else | else-if | ||||
Ada | Da | Da | Da | Da | Ne | ? |
C i C++ | Da | Da | nije potrebno [2] | propadanje | Ne | Ne |
Fortran | Da | Da | Da | Da | Da | ? |
Perl | Da | Da | Da | Ne | Ne | ? |
PHP | Da | Da | Da | propadanje | Ne | ? |
Haskell | Da | Da, zahtijevano | nije potrebno [2] | nije potrebno [3] | Ne | Da |
- a Ovo se odnosi na sparivanje uzoraka kao istaknuti uvjetni konstrukt u programskom jeziku - kao suprotnost pukoj podršci za sparivanje uzoraka stringova, kao što je podrška za regularne izraze.
- a b Vrlo čest
else if
u C porodici jezika, kao i u Haskellu, nije svojstvo jezika, već skup ugniježđenih i neovisnih if then else naredbi kombiniranih s osobitim izgledom izvornog koda. Međutim, ovo znači da odvojen else-if konstrukt nije ustvari ni potreban u ovim jezicima. - a U Haskellu odvojeni konstrukt izbora konstanti nije ni potreban, s obzirom na to da se ista funkcionalnost da ostvariti sparivanjem uzoraka.