Fundamentele programării (VI) - Scala

Pe măsură ce scriem din ce în ce mai mult cod, acesta devine mai greu de urmărit. Vă amintiți de lunga secvență if, else, if din episodul anterior? Atunci am avut o soluție cu match, dar în alte situații instrucțiunile nu au astfel de caracteristici comune. Totuși, am putea dori să le grupăm cumva. Am văzut că avem grupuri de instrucțiuni, dar nici acestea nu sunt utile decât în anumite situații.

Ar fi frumos dacă am putea împărți codul în bucățele mici, ușor de înțeles, pe care să le folosim cum vrem. Să ne imaginăm că vrem să tipărim versurile din Gaudeamus. Deocamdată, programul nostru ar arăta cam așa:

Cam lung și monoton, nu?

Împărțirea în funcții

Am spus că am vrea să împărțim acest cod în bucățele mai mici. O putem face oricum, dar ar fi bine ca acele bucățele să aibă totuși un sens. De data aceasta este natural să alegem o împărțire pe strofe. Fiecare strofă va fi scrisă de o bucată de cod; o astfel de bucată de cod poartă denumirea de funcție. Prezentăm noua variantă a codului și apoi vom discuta mai pe larg despre funcții (ce sunt și cum sunt create).

Vedem acum șapte noi porțiuni de cod, care încep cu ciudatul def. Să ignorăm deocamdată acest cuvânt...

Urmează o denumire; acesta este numele funcției. Acesta este urmată de semnul egal. Avem apoi o paranteză deschisă, urmată imediat de una închisă. Cam ciudat, dar să ignorăm și acest aspect deocamdată (vom vedea în episodul următor mai multe despre aceste paranteze). După aceea avem un simplu bloc de instrucțiuni; acesta este numit corpul funcției.

În Scala, codul pe care l-am scris se află între acoladele care urmează după linia care începe cu object Main extends App. Funcțiile le definim tot aici. După definiția funcțiilor vedem șapte linii care conțin numele celor șapte funcții, urmate de câte o paranteză deschisă și câte una închisă. Acestea sunt instrucțiuni prin care spunem că dorim să se execute codul corespunzător unei funcții. Ele poartă denumirea de apeluri de funcții.

Instrucțiunile din interiorul unei funcții nu se execută decât dacă funcția este apelată. Dacă am șterge liniile 64 - 70 versurile nu ar mai fi afișate. De fapt, acum putem alege ce strofe dorim să afișăm. Prin eliminarea unei linii, decidem că o anumită strofă nu trebuie afișată. Vă mai amintiți de comentarii? Putem să nu ștergem linia, ci doar să o comentăm.

Funcții apelate din funcții

Corpul funcției poate conține orice instrucțiuni, inclusiv un apel al unei alte funcții. Să presupunem că primele versuri din prima strofă sunt speciale; la fel și ultimul vers (vom vedea mai târziu de ce). Poate am dori să împărțim codul corespunzător funcției strofa1 în mai multe bucățele: primele două versuri, următoarele două și ultimul. Secțiunea corespunzătoare a codului ar putea arăta astfel:

Avem acum o funcție care apelează alte trei funcții. Putem face același lucru și pentru funcțiile corespunzătoare celorlalte strofe.

În Scala, o funcție poate fi definită și în interiorul altei funcții. Astfel, bucata de cod poate fi scrisă și așa:

Apeluri multiple

Am spus că o funcție este executată doar dacă este apelată. Dar, ce ne împiedică să o apelăm de mai multe ori? Nimic! Lăsăm nemodificate funcțiile strofa1inceput, strofa1mijloc și strofa1sfarsit, dar modificăm funcția strofa1 astfel:

Acum funcția strofa1inceput este apelată de două ori, deci va fi executată de două ori, deci primele două versuri vor fi afișate de două ori. Similar, funcția strofa1sfarsit este apelată de două ori, deci va fi și ea executată de două ori și ultimul vers va fi și el afișat de două ori.

De ce am face așa ceva? Când este cântat Gaudeamus, primele două versuri din fiecare strofă sunt repetate; la fel și ultimul vers. Deci, dacă am ales o împărțire potrivită a funcțiilor, am putut trece ușor de la poezie la cântec.

Ne putem gândi și la alte situații în care apelurile multiple ar putea fi utile. De exemplu, am putea avea un cântec cu refren. Funcția care afișează refrenul ar putea fi apelată de mai multe ori.

Va urma

În cadrul episodului următor, vom vedea că putem crea funcții puțin mai "inteligente". Nu vom avea doar o succesiune de instrucțiuni care se execută tot timpul în același fel, ci vom putea avea comportamente diferite în funcție de modul în care este apelată o funcție.