Propratni efekti

S Vikipedije, slobodne enciklopedije

U informatici i računarstvu, za potprogram ili izraz kažemo da ima propratni efekat ako menja neko stanje ili ima primetnu interakciju sa pozivajućom funkcijom. Na primer, određena funkcija može da modifikuje globalne promenljive ili lokalne promenljive, neki od argumenata, diže izuzetak, upisuje podatke u datoteku ili na standardni izlaz, čita podatke, ili pozove drugu funkciju koja ima propratni efekat. Kada postoje propratni efekti, ponašanje programa može da zavisi od redosleda evaluacije. Razumevanje i debagovanje funkcije sa propratnim efektima zahteva znanje o kontekstu i mogućim redosledom pozivanja funkcija.[1][2]

Propratni efekti su najčešći način na koji program komunicira sa spoljnim svetom (ljudima, sistemskim fajlovima, drugim računarima na mreži). Stepen korišćenosti propratnih efekata zavisi od programske paradigme. Imperativno programiranje je poznato po čestom korišćenju propratnih efekata.

U funkcionalnom programiranju, propratni efekti se retko koriste. Nedostatak propratnih efekata čini ih lakšim za verifikaciju programa. Funkcionalni jezici kao Standard ML, Scheme i Skala ih ne zabranjuju, ali je obično na programerima da ih izbegavaju.[3] Funkcionalni jezik Haskel izražava propratne efekte kao što su Ulaz/Izlaz i druga izračunavanja sa stanjima koristeći monadične akcije.[4][5]

Asembler programeri moraju da paze na skrivene propratne efekte — instrukcije koje modifikuju deo procesorskih stanja koja nisu spomenuta u instrukcijskoj mnemonici. Klasičan primer skrivenog propratnog efekta je aritmetička instrukcija koja implicitno modifikuje stanje registra (skriveni propratni efekat) dok eksplicitno modifikuje registar (otvoren efekat). Jedna moguća mana skupa instrukcija sa skrivenim propratnim efektima je to što, ako više instrukcija ima propratne efekte na jednom stanju, kao stanja registara, onda logika potrebna za ažuriranje tog stanja redom može postati usko grlo. Problem je posebno izražen na nekim procesorima dizajniranim pajplajningom (od 1990) ili vanrednim izvršavanjem. Takvi procesori mogu da zahtevaju dodatnu kontrolu kola da bi otkrili skrivene propratne efekte i zaustavili pajplajn ako sledeća instrukcija zavisi od rezultata ovih efekata.

Referentna transparentnost[uredi | uredi izvor]

Odsustvo propratnih efekata je neophodan, ali ne i dovoljan uslov za referentnu transparentnost. Referentna transparentnost znači da izraz (kao što je funkcijski poziv) može biti zamenjen njegovom vrednošću; ovo zahteva da izraz nema propratne efekte i da bude čist (uvek vraća isti rezultat za isti unos).

Privremeni propratni efekti[uredi | uredi izvor]

Propratni efekti prouzrokovani vremenom potrebnim za izvršavanje operacije su obično ignorisani kada se govori o propratnim efektima i referentoj transparentnosti. Ima slučajeva gde su operacije ubačene baš zbog njihovih privremenih propratnih efekata npr. Sleep(5000) ili for(int i=0; i < 10000; i++){}. Ove instrukcije ne menjaju stanje sem vremena za njihovo izvršavanje.

Idempotencija[uredi | uredi izvor]

Za funkciju sa propratnim efektima se kaže da je idempotentna pod sekvencijalnom kompozicijom (f; f) ako, kada je pozvana sa istim argumentom dvaput, drugi poziv vraća istu vrednost i nema propratne efekte koji ga mogu razlikovati od prvog poziva. Na primer, razmotrimo:

x = 0;
def xSetter(n):
    global x
    x = n
xSetter(5)
xSetter(5)

Ovde, xSetter je idempotentan zato što drugi poziv xSetter (sa istim argumentom) vraća istu vrednost i ne menja vidljivo stanje programa. Primetimo da je ovo različito od idempotencije pod kompozicijom funkcija (f ∘ f): xSetter nije idempotentan pod kompozicijom funkcija jer xSetter(5) i xSetter(xSetter(5)) postavljaju x na različite vrednosti gde povratna vrednost xSetter jeste x; u ovom primeru povratna vrednost je uvek 5.

Primer[uredi | uredi izvor]

Česta demonstracija ponašanja propratnih efekata je operator dodele u programskom jeziku C++. Na primer, naredba dodela vraća desni operand i ima propratni efekat dodele te vrednosti promenljivoj. Ovo omogućava sintaksički čistu višestruku dodelu:

int i, j;
i = j = 3;

Pošto je operator dodele desno asocijativan, ovo je ekvivalentno sa

int i, j;
i = (j = 3); // j = 3 враћа 3, који се затим додељује променљивој i

Gde je rezultat dodeljivanje vrednosti 3 izrazu "j" koji dobija vrednost promenljive "i". Ovo predstavlja potencijalni problem za programere početnike koji mogu da greškom zamene

while (b == 10) {} // Испитује да ли је b једнако 10

sa

// Функција доделе враћа 10
// које се аутоматски кастује на "true"
// па се петља никад не завршава
while (b = 10) {}


Reference[uredi | uredi izvor]

  1. ^ “Research Topics in Functional Programming” ed. D. Turner, Addison-Wesley, (1990). str. 17–42. Retrieved from: Hughes, John, Why Functional Programming Matters (PDF) 
  2. ^ Collberg, CSc 520 Principles of Programming Languages, Department of Computer Science, University of Arizona 
  3. ^ Matthias Felleisen et al., How To Design Programs, MIT Press
  4. ^ Haskell 98 report, http://www.haskell.org.
  5. ^ Imperative Functional Programming, Simon Peyton Jones and Phil Wadler, Conference Record of the 20th Annual ACM Symposium on Principles of Programming Languages, pages 71—84, 1993