Кондиционал (рачунарско програмирање)

У информатици, условне изјаве, условни изрази и условне конструкције су функције  програмског језика, које извршавају различита израчунавања или различите акције у зависности од тога да ли је програмерски одређен булов услов оценио на тачно или нетачно. Осим у случају предвиђања огранка, ово се увек постиже тако што се селективно мења управљање током засновано на неком услову.

Диаграм If тока
Диаграм "If-then-else"

У језицима императивног програмирања, термин "условна изјава" се обично користи, док у  функционалном програмирању, термини "условни изрази" или "условна конструкција" су пожељни, зато што ови појмови имају различита значења.

Иако динамична депеша обично није класифицирана као условна конструкција, она представља још један начин бирања између алтернатива за време рантајма.

If–then(–else)

уреди

if–then конструкција (понекад звана if–then–else) је заједничка за многе порграмске језике. Иако синтакса поприлично варира од језика до језика, основна структура (у облику псеудокода) изгледа овако:

 If (boolean condition) Then
    (consequent)
 Else
    (alternative)
 End If

Када интерпретарор пронађе реч  If, он очекује булов услов – на пример, x > 0, што значи "променљива x садржи број који је већи од нуле" – и процењује тај услов. Ако је услов true, изјава која следи после then се извршава. Иначе, извршавање се наставља у следећој грани – било у else блоку (која је обично опционална), или ако не постоји else грана, онда после end If.

После извршавања било које гране, управљање током се враће на тренутак после end If.

У првим програмским језицима, посебно неки дијалекти Бејсика у кућним рачунарима 1980-их година,  if–then изјава је могла само да садржи GOTO изјаве. Ово је довело до стила програмирања тешког за читање који је познат као шпагети програмирање, са програмима у стилу који се називао шпагети код. Као резултат, структурирано програмирање, које дозвољава (готово) произвољним изјавама да буду стављене у изјавне блокове унутар if изјаве, је добило на популарности, док није постало норма чак и у већини Бејсик програмских кругова. Такви механизми и принципи су базирани на старијој али много напреднијој породици језика Алгол, и језици налик на Алгол као што су Паскал и Модула-2 су утицали на модерне Бејсик варијанте дуги низ година. Док је могуће при употреби само GOTO изјава у if-then изјавама, написати програме који нису шпагети код и који су структуирани и читљиви колико и програми написни у структуираном програмском језику, структуирано програмирање ово чини лакшим и оно га спроводи. Структуиране if-then-else изјаве као на примеру изнад су један од кључних елемената структуираног програмирања, и оне су присутне у најпопуларнијим програмским језицима високог нивоа као што су C, Јава, Јаваскрипт и Вижуал бејсик .

Субтилност је у томе да опционална else клаузула која се може њаћи у многим језицима значи да је контекстно слободна граматика двосмислена, пошто се груписани кондиционали могу анализирати на различите начине. Конкретно,

if a then if b then s else s2

се може анализирати као

if a then (if b then s) else s2

или

if a then (if b then s else s2)

у зависности да ли је else повезано са првим  if или другим if. Ово је познато као климаво else проблем, и тај проблем се решава на различите начине, у зависности од језика.

Коришћењем else if, могуће је комбиновати веше услова. САмо изјаве после првог услова за које се утврди да су истините ће бити извршене. Све остале изјаве ће бити прескочене. Изјаве

if услов then
   --изјаве
elseif услов then
    -- још изјава
elseif услов then
    -- још изајва;
...

else
    -- друге изјаве;
end if;

elsif, у Ади, је просто шећер синтаксе за else после кога иде if. У Ади, разлика је у томе да је само једно end if потребно, ако неко користи elsif уместо else после кога иде  if. Ово је слично у Перл, који обезбеђује кључну реч elsif да би избегао велики број протеза које би биле потребне од стране више if и else изјава и такође у Пајтону, који користи специјалну кључну реч elif зато што је структура означена са увлачењем а не са протезама, тако да би репетитивна употреба else и if захтевала повећано увлачење после сваког услова. Слично, раније јуникс љуске (касније сакупљене у Посикс синтаксу љуске [1]) користе elif такође, али дајући избор разграничавања са празним простором, линијама, или оба.

Међутим, у многим језицима који воде директно порекло од Алгола, као што су Алгол68, Симула, Паскал, BCPL и C, ова специјална синтакса за else if није присутна, није присутна ни у многим синтаксним дериватима C-а, као што су Јава, ECMA-скрипт, PHP, и тако даље. Ово ради зато што у овим језицима, било који један израз (у овом случају if конд...) може да прати кондиционал а да не буде уклопљен у блок.

Овај дизајнерски избор има малу "цену" у томе да код else if гране, ефективно, додаје један више ниво груписања, компликујући посао за неке компајлере (или за њихове реализаторе), који морају да нализирају и имплементирају поризвољно дугачке else if ланце рекурзивно.

Ако сви термини у секвенци кондиционала тестирају вредност једног израза (нпр, if x=0 ... else if x=1 ... else if x=2...), онда се та алтернатива назива изјава замене, ил изјава случаја или изјава одабира. С друге стране, у језицима који немају изјаву замене, ове изваје могу бити произведене од стране секвенце else if изјава.

If-then-else изрази

уреди

многи језици подржавају if изразе, који су слични if изјавама, али враћају вредност као резултат. Стога, они су истински изрази (који процењују на вредност), не изјаве (које мењају стање програма или врше неку врсту акције).

Алгол породица

уреди

Алгол 60 и неки други чланови Алгол породице дозвољавају if-then-else као израз:

  мојапроменљива := if x > 10 then 1 else 2

Lisp дијалекти

уреди

У дијалектима Lisp-а -- Ским, Ракет и Common Lisp -- од којих је прва била инспирисана у великој мери од стране Алгола:

 ;; Scheme
 (define myvariable (if (> x 10) 1 2))   ; Додељује ‘myvariable’ на 1 или 2, у зависности од вредности ‘x’
 ;; Common Lisp
 (let ((x 5))
   (setq myvariable (if (> x 10) 1 2)))  ; Додељује ‘myvariable’ на 2

Хаскл

уреди

У Хаскл 98, постоји само if израз, а не if изјава, и else део је обавезан, како сваки израз мора да има неку вредност.[2] Логика која би била изражена са кондиционалима у другим језицима је обично изражена са подударањем шаблона у рекурзивним функцијама.

Зато што је Хаскл лењ, могуће је писати контролне структуре, као што су if, као обичне изразе; лења евалуација значи да if функција може да процени само услов и одговарајућу грану (где би строги језик процењивао сва три). Може се написати овако:[3]

 if' :: Bool -> a -> a -> a
 if' True x _ = x
 if' False _ y = y

Језици налик на C

уреди

C и језици налик на C имају специјалан тернарни оператер (?:) за кондиционалне изразе са функцијом која може бити описана од стране шаблона на овај начин:

услов ? процењен-када-true : процењен-када-false

Ово значи да може бити убачен у изразе, за разлику од if-изјава, у језицима налик на C:

моја_променљива = (x > 10) ? "foo" : "bar"; // У језицима налик на C

који могу бити поређени са if-then-else изразима Алгол породице (и слично у Руби и Скали, међу осталима).

Да би постигли исту ствар користећи if-изјаву, за ово би било потребно више од једне линије кода (под типочним конвенцијама израза):

if (x > 10)
  моја_променљива = 'foo';
else
  моја_променљива = 'bar';

Неки тврде да је изричита if/then изјава лакша за читање и да се може саставити на ефикаснији код од тернарног оператера,[4] док други тврде да су концизни изрази лакши за читање него изјаве прострањене на неколико линија.

Унутар Вижуал бејсика

уреди

У Вижуал бејсику и неким другим језицима, функција која се назива IIf је обезбеђена, која се може користити као кондиционални израз. Међутим, она се не понаша као прави кондиционални израз, зато што су и true и false гране увек процењене; то само значи да је резултат једне од њих одбачен, док је резултат друге враћен од стране IIf функције.

Аритметичко if

уреди

До Фортрана 77, језик Фортаран има "аритметичку if" изјаву која је на пола пута између обрачунатог IF и изјаве случаја, базирану на трихотомији  ,  ,  . Ово је најранија условна изјава у фортрану:[5]

IF (e) ознака1, ознака2, ознака3

Где је e било који нумерички израз (не мора бити цео број); ово је еквивалентно са

IF (e .LT. 0) GOTO ознака1
IF (e .EQ. 0) GOTO ознака2
GOTO ознака3

Зато што је ово аритметичко IF еквивалентоно вишеструким GOTO изјавама које се могу преместити било где, оно се сматра да је неструктуирана контролна изјава, и не треба се користити ако се могу користити више структуиране изјаве. У пракси је уочено да је већина аритметичких IF изјава референцирала следећу изјаву са једном или две ознаке.

Ово је била једина условна контролна изјава у оригиналној имплементацији Фортрана на IBM 704 рачунару. На том рачунару је тест-и-грана op-код имао три адресе за за та три стања. Други рачунари би имали "застава" регистре као што су позитива, нула, негатива, једнакост, преливање, ношење, повезане са последњом аритметичком операцијом и они би користили инструкција као што су 'Разгранај ако је акумулатор негативан' затим 'Разгранај ако је аумулатор нула' или слично. Имајте на уму да се израз процењује само једном, и у случајевима као што је цео аритметички број где може доћи до преливања, такође би се разматрало преливање или ношење застава .

Објектно-оријентисана имплементација у Smalltalkу

уреди

За разлику од других језика, у Smalltalkу условна изјава није језичка конструкција али је дефинисана у класи Boolean као апстрактна метода која узима два параметара, оба затварача. Boolean има две подкласе, True и False, где обе дефинишу методу, True извршава само прво затварање, False извршава само друго затварање.[6]

var = condition 
    ifTrue: [ 'foo' ]
    ifFalse: [ 'bar' ]

Изјаве случаја и замене

уреди

Изјаве замене (у неким језицима, изјаве случаја или гране на више начина) упоређују дату вредност са специфизираном константом и предузимају мере према првој константи која одговара. Обично постоји одредба за подразумевану акцију ('else','otherwise') коју треба предузети ако ниједно спаривање не успе. Изјаве замене могу дозволити компајлер оптимизације, као што су лукап табеле. у динамичким језицима, случајеви можда неће бити ограничени на сталне изразе, и можда се прошире на подударање шаблона, као у шел скрипт примеру са десне стране, где '*)' имплементира уобичајен случај за регуларни израз који се подудара са сваким стрингом.

Паскал: C: Шел скрипте 
case someChar of
  'a': actionOnA;
  'x': actionOnX;
  'y','z':actionOnYandZ;
  else actionOnNoMatch;
end;
switch (someChar) {
  case 'a': actionOnA; break;
  case 'x': actionOnX; break;
  case 'y':
  case 'z': actionOnYandZ; break;
  default: actionOnNoMatch;
}
case $someChar in 
   a)    actionOnA; ;;
   x)    actionOnX; ;;
   [yz]) actionOnYandZ; ;;
  *)     actionOnNoMatch  ;;
esac

Уклапање шаблона

уреди

Уклапање шаблона се можда види као софистициранија алтернатива и за if-then-else изјаве и изјаве случаја. Она је доступна у многим програмским језицима са функционалним програмским карактеристикама, као што су Волфрам језик, ML и многи други. Ево простог примера написаног у OCaml језику:

 match fruit with
 | "apple" -> cook pie
 | "coconut" -> cook dango_mochi
 | "banana" -> mix;;

Моћ укапања шаблона је способност да концизно слаже не само акције али и вредности у обрасце података. Ево примера написаног у Хаскл који илуструје обе ове карактеристике:

 map _ []      = []
 map f (h : t) = f h : map f t

Овај код дефинише мапу, функције која примењује први аргумент (функцију) сваком од елемената другог аргумента (листе), и враће резултујућу листу. Две линије су две дефиниције функције за две врсте аргумената могућих у овом случају – онај у коме је листа празна (само врати празну листу) и други случај када листа ниеј празна.

Уклапање шаблона стриктно говорећи није увек изборна конструкција, зато што је могуће у Хасклу написати само једну алтернативу, која је загарантована да увек пуде упарена – у овој ситуацији, се не користи као изборна конструкција, већ само као начина везивања имена са вредностима. Међутим, често се користи као изборна конструкција у језицима у којима је доступна.

Кондиционали базирани на хешу

уреди

У пограмским језицима који имају асоцијативне низове или упоредиве структуре, као што су Пајтон, Перл, PHP или Objective-C, идиоматски је да их користите за имплементацију условног задатка.[7]

љубимац = raw_input("Унесите тип љубимца којег желите да именујете: ")
познати_љубимци = {"Пас": "Fido",
              "Мачка": "Meowsles",
              "Птица": "Tweety"}
моје_име = познати_љубимци[љубимац]

У динамичким језицима који имају анонимне функције или које дозвољавају програмеру да додели именовану функцију варијаблној референци, условни ток се може имплементирати коришћењем хеша као прескок стола.

Предвиђање огранака

уреди

У асемблерским језицима, предвиђање огранака је функција одређених процесорских (централних процесорских јединица) (CPU) комплета инструкција која дозвољава суловно извршавање инструкција, без потребе да се извршавају скупи условни скокови.

Упућивање изброног система

уреди

Ова табела се односи на велики број недавних језичких спецификација за сваки језик. За језике који немају спецификацију, последња званично пуштена имплементација је она на коју се односи.

Програмски језик Структурно if замена-одабир-случај Аритметичко if Укалпање шаблона[A]
then else else-if
Ада Да Да Да Да Не Не
C, C++ Да Да Непотребан[B] Пропао Не Не
C# Да Да Непотребан[B] Да Не Не
Кобол Да Да Непотребан[B] Да Не Не
Ајфел Да Да Да Yes Не Не
F# Да Да Да Непотребан[C] Не Да
Фротран 90 Да Да Да Да Да Не
Гоу Да Да Непотребан[B] Да Не Не
Хаскл Да Needed Непотребан[B] Непотребан[C] Не Да
Јава Да Да Непотребан[B] Пропао[8] Не Не
Екмаскрипт 

(Јаваскрипт)

Да Да Непотребан[B] Пропао[9] Не Не
Матхематика Да Да Да Да Не Да
Оберон Да Да Да Да Не Не
Перл Да Да Да Да Не Не
PHP Да Да Да Пропао Не Не
Паскал, Објектни паскал

(Делфи)

Да Да Непотребан Да Не Не
Пајтон Да Да Да Не Не Не
КуикБејсик Да Да Да Да Не Не
Руби Да Да Да Да Не Не
Скала Да Да Непотребан[B] Пропао Не Да
SQL Да[S] Да Да Да[S] Не Не
Вижуал Бејсик, класик Да Да Да Да Не Не
Вижуал Бејсик.NET Да Да Да Да Не Не
Виндоус

Пауршел

Да Да Да Пропао Не Не
  1. ^ Ово се односи на уклапање шаблона као посебну условну конструкцију у програмском језику – насупрот само подршци уклапања шаблона стингова, као што је подршка регуалрни израз support.
  2. 1 2 3 4 5 Често сусретано else if у C породици језика, а такође и у Коболу и Хасклу, није функција језика већ је скуп угнежђених и независних if then else изјава комбинованим са одређеним изгледао изворног кода. Међутим, ово такође значи да јасна else-if конструкција није заиста потребна у овим језицима.
  3. 1 2 У Хасклу и F#, посебна константа изборне конструкције је непотребна, јер исти задатак може бити урађен с уклапањем шаблона.
  4. 1 2 SQL има две сличне конструкције које испуњавају обе улоге, обе уведене у SQL-92. "претражен CASE" израз CASE WHEN cond1 THEN expr1 WHEN cond2 THEN expr2 [...] ELSE exprDflt END кади као if ... else if ... else, док "обичан CASE" израз: CASE expr WHEN val1 THEN expr1 [...] ELSE exprDflt END ради као изјава замене. За детаље и примере погледајте Case (SQL).

Види још

уреди

Референце

уреди
  1. ^ POSIX стандардна синтакса љуске
  2. ^ Хаскл 98 језик и библиотеке: Измењени извештај
  3. ^ "If-then-else Proposal on HaskellWiki"
  4. ^ „Efficient C Tips #6 – Don’t use the ternary operator « Stack Overflow”. Embeddedgurus.com. 18. 02. 2009. Приступљено 07. 09. 2012. 
  5. ^ „American National Standard Programming Language FORTRAN”. 03. 04. 1978. Архивирано из оригинала 11. 10. 2007. г. Приступљено 09. 09. 2007. 
  6. ^ „VisualWorks: Conditional Processing”. 16. 12. 2006. Архивирано из оригинала 22. 10. 2007. г. Приступљено 09. 09. 2007. 
  7. ^ „Pythonic way to implement switch/case statements”. Архивирано из оригинала 20. 01. 2015. г. Приступљено 19. 01. 2016. 
  8. ^ Java.sun.com, Јава језичка спецификација, треће издање.
  9. ^ Ecma-international.org Архивирано на сајту Wayback Machine (12. април 2015) Екма скрипт језичка спецификација, пето издање.

Спољашње везе

уреди