Zahărul sintactic într- un limbaj de programare este o caracteristică sintactică care nu afectează comportamentul programului, dar face limbajul mai ușor de utilizat.
Poate fi orice element de sintaxă care oferă programatorului o modalitate alternativă de a scrie un construct sintactic deja în limbaj, care este mai convenabil, sau mai concis, sau similar cu un alt mod obișnuit de scriere, sau ajută la scrierea programelor în stil bun.
Zahărul sintactic este orice element sintactic, mecanism, metodă de descriere disponibil într-un limbaj de programare care dublează un alt element sau mecanism disponibil în limbaj, dar este mai convenabil de utilizat, sau este mai concis, sau arată mai natural sau este mai familiar ( similar cu elemente similare din alte limbi), sau pur și simplu mai bine perceput atunci când citește un program de către o persoană. Punctul cheie este că zahărul sintactic, teoretic, poate fi întotdeauna eliminat dintr-o limbă fără a-și pierde capacitățile - tot ceea ce poate fi scris folosind zahăr sintactic poate fi scris în aceeași limbă fără el. Astfel, zahărul sintactic este menit doar să faciliteze scrierea programului de către programator.
Conceptul de zahăr sintactic este în mare măsură arbitrar. Utilizarea lui presupune că din întregul set de construcții sintactice disponibile în limbă se poate evidenția un „mult de bază” care asigură funcționalitatea limbajului și mijloace sintactice suplimentare, care, dacă se dorește, pot fi exprimate folosind setul de bază. ; acesta din urmă va fi zahăr sintactic pentru o limbă dată. Cu toate acestea, multe modele sunt interschimbabile și este departe de a fi întotdeauna posibil să spunem cu certitudine care dintre ele sunt de bază și care sunt suplimentare. De exemplu, există patru tipuri de bucle în Modula-2 : o buclă de precondiție , o buclă de postcondiție , o buclă de pas și o buclă necondiționată . Teoretic, primele trei tipuri de cicluri pot fi ușor exprimate în termenii ultimului. Sunt, deci, zahăr sintactic? De obicei, ei nu spun așa, deși formal se încadrează în definiția de mai sus.
Atribuirea unor construcții zahărului sintactic este ambiguă din motive istorice. De exemplu, limbajul C și descendenții săi au operatorii de alocare increment , decrement și compus ( ++, --, +=, -=și alții). Introducerea acestor operatori în limbaj a fost cauzată de necesitatea de a sprijini optimizarea manuală a programelor, deoarece codul care le folosea putea fi tradus în instrucțiuni de mașină mai eficiente (“ ++a” a fost tradus într-o instrucțiune INC, iar o expresie similară „ a=a+1” în un întreg grup de instrucțiuni). Dezvoltarea tehnologiei de optimizare a codului a făcut ca o astfel de optimizare manuală să fie inutilă; acum compilatoarele generează același cod pentru versiunile „lungă” și „scurtă” ale operațiunii. Drept urmare, operatorii abreviați s-au transformat în zahăr sintactic, deși nu au fost inițial.
În unele cazuri, conceptul de „zahăr sintactic” este interpretat mai larg decât „un mod diferit de a scrie pentru construcțiile sintactice deja existente”. Jack Crenshaw în Să construim un compilator! [1] aplică acest termen elementelor sintactice care nu sunt necesare pentru compilarea corectă a programului, dar sunt incluse în limbaj numai pentru comoditatea programatorului și pentru lizibilitatea programului:
La urma urmei, și oamenii ar trebui să citească programe... Jetoanele de zahăr servesc drept repere utile pentru a vă ajuta să rămâneți pe drumul cel bun...
Un exemplu de astfel de zahăr sintactic este „atunci” în declarația „dacă” sau „do” în instrucțiunea „în timp ce”, precum și punctul și virgulă: compilatorul determină fără ambiguitate sfârșitul condiției și locul în care instrucțiunea se termină fără ele, dar prezența acestor constructe face programul mai ușor de citit. Evident, interpretarea restrânsă a conceptului de „zahăr sintactic” este incompatibilă cu cea largă: în C sau Pascal este imposibil să scrii operatorii într-un mod diferit, fără „atunci”, „do” și punct și virgulă. Într-un astfel de caz, este potrivit să vorbim de „ gunoaie de sintaxă ”. Având în vedere că cuvintele suplimentare într-un limbaj de programare sunt simboluri suplimentare, ar fi mai corect să folosim termenul de „ gunoi lexical ” [2] . Pe de altă parte, nu este în întregime corect să numim astfel de elemente „extra” ale limbajului „gunoaie”, deoarece, în realitate, pot afecta semnificativ calitatea programării, deoarece prezența redundanței în sintaxă facilitează compilatorul. pentru a localiza erorile din cod. Luați în considerare un exemplu într-un limbaj de tip BASIC condiționat, în care cuvântul atunci este opțional în instrucțiunea condiționată și un punct și virgulă între declarații, iar semnul egal poate denota, în funcție de poziție, atât egalitatea logică, cât și atribuirea:
dacă a > b și k = 20 f = 10Aici „a>b și k=20” este condiția, iar „f=10” este ramura „aceea”. Cu toate acestea, dacă programatorul omite sau elimină accidental operatorul „și”, constructul devine:
dacă a > b k = 20 f = 10Programul va rămâne corect din punct de vedere sintactic, dar condiția va fi pur și simplu „a>b”, iar ramura „aceea”, în funcție de regulile limbajului, va fi fie „k=20”, care s-a transformat dintr-o condiție în o atribuire sau ambii operatori „k=20 f= zece”. Ca urmare a erorii, condiția va fi încălcată și valoarea variabilei k va fi distrusă. Deoarece programul va rămâne corect din punct de vedere sintactic atunci când este introdusă o eroare logică, compilatorul nu va observa eroarea. Solicitarea prezenței obligatorii a cuvântului de serviciu „atunci” între condiție și operator va determina compilatorul să detecteze o eroare de sintaxă în condiție. Punctul și virgulă obligatoriu între operatori va permite, de asemenea, compilatorului să detecteze o eroare - absența punctului și virgulă după operatorul „k=20”. Astfel, prezența jetoanelor „de zahăr”, ca orice redundanță în limbaj în general, duce la faptul că erorile logice din cod se transformă în unele sintactice și pot fi detectate de compilator.
Termenul de zahăr sintactic a fost inventat de Peter J. Landin în 1964 pentru a descrie sintaxa de suprafață a unui limbaj simplu asemănător Algol , definit semantic în termeni de expresii aplicative de calcul lambda , urmate de o înlocuire pur lexicală a lui λ cu where.
Matricele din C sunt blocuri din memorie . Elementele matricei sunt accesate printr-un pointer la începutul blocului de memorie (adică la începutul matricei) și offset-ul elementului în raport cu adresa de pornire. Aceasta poate fi scrisă fără a folosi sintaxa specială pentru tablouri ( a - pointer la începutul matricei, i - index element): *(a + i), dar limbajul oferă o sintaxă specială: a[i]. Interesant este că se poate folosi și forma i[a], care este destul de logică datorită comutativității operației de adunare.
Redefinirea operatorului , susținută de multe limbaje de programare, poate fi, de asemenea, atribuită zaharului sintactic . În principiu, orice operație poate fi încadrată ca o procedură (funcție, metodă). Redefinirea operatorului vă permite să efectuați operațiuni create de programator extern în același mod ca și cele încorporate în limbaj [3] [4] .
Un alt exemplu de zahăr sintactic este conceptul de „proprietăți” susținut de multe limbaje de programare moderne. Aceasta se referă la declarația din clasa de pseudo-câmpuri care se comportă extern ca câmpurile de clasă (au nume, tip, permit atribuirea și citirea), dar în realitate nu sunt. Fiecare acces la proprietate este tradus de compilator într-un apel de metodă de acces. Proprietățile sunt complet inutile (accesorii pot fi, de asemenea, apelați direct) și sunt utilizați doar pentru comoditate, deoarece codul care utilizează proprietăți pare oarecum mai simplu și mai clar.
Nu toți programatorii consideră prezența zahărului sintactic în limbajele de programare și utilizarea acestuia de către programatori ca un avantaj. Este cunoscut punctul de vedere al lui Niklaus Wirth , care este împărtășit de o parte a comunității de programare: potrivit acestuia, orice extensie a limbajului care nu este cauzată de necesitate îl agravează, deoarece duce la complicarea traducătorului și, în consecință, la o scădere a fiabilității și performanței sale. În același timp, complexitatea învățării limbii și complexitatea menținerii programelor sunt în creștere. În plus, însuși faptul că există instrumente sintactice suplimentare joacă adesea un rol provocator: îl încurajează pe programator să recurgă la diverse trucuri sintactice în loc să analizeze problema mai profund și să implementeze algoritmi mai eficienți. Aceste opinii se reflectă în limbile familiei Oberon , care sunt foarte simple și practic lipsite de zahăr sintactic.
Este binecunoscut aforismul lui Alan Perlis : „Zăhărul sintactic provoacă cancer de punct și virgulă” . Punctul și virgulă ( ;), deși este o parte obligatorie a celor mai populare limbaje de programare, chiar dacă inutilă într-o limbă nouă, este lăsată ca element opțional, deoarece majoritatea programatorilor au un obicei puternic de a-l folosi. În original, aforismul joacă pe consonanța cuvintelor englezești punct și virgulă („punct și virgulă”) și colon , acesta din urmă înseamnă nu numai colon, ci și intestinul gros ( cancer de colon - „cancer de colon”).
De cele mai multe ori, critica este îndreptată către tipuri individuale, frecvent întâlnite de zahăr sintactic: operații de redefinire, proprietăți, operații complexe (cum ar fi operația condiționată ternară ). Argumentele criticilor, practic, se rezumă la faptul că astfel de instrumente, de fapt, nu fac programul mai simplu, mai clar, mai eficient sau mai scurt, ci duc la o risipă suplimentară de resurse și complică percepția, și deci menţinerea programului.
Spre deosebire de „zahăr sintactic”, conceptul de „ sare sintactică ” ( sare sintactică în engleză ) [5] din jargonul programatorilor se referă la constructe inutile din punct de vedere tehnic dintr-un limbaj de programare pe care regulile limbajului cer să le folosească atunci când se execută potenţial nesigur. actiuni. Ele sunt introduse în limbaj numai astfel încât, prin utilizarea lor, programatorul confirmă astfel că acțiunea dubioasă a fost întreprinsă de el în mod conștient și nu este o eroare accidentală sau rezultatul unei neînțelegeri. La fel ca „zahărul sintactic”, „sarea sintactică” nu extinde capacitățile limbajului și nu este nevoie de compilator pentru a compila corect programul; este destinat exclusiv persoanelor care folosesc acea limbă. Un exemplu clasic de „sare sintactică” bine-cunoscută și utilizată pe scară largă este comenzile de conversie a tipurilor de date încorporate care se găsesc în aproape orice limbaj tipizat static. Formal, aceste comenzi sunt de prisos (după cum demonstrează clasicul C, în care orice conversie de tip este permisă și se face automat), dar în limbile în care utilizarea lor este obligatorie, programatorul este obligat să acorde atenție de fiecare dată când efectuează un potențial amestecare de tip periculos, care indică adesea o eroare logică în program. În funcție de rigoarea limbajului de programare, utilizarea unei „sare de sintaxă” poate fi necesară sau opțională. În primul caz, compilatorul percepe absența sa ca pe o eroare de sintaxă, în al doilea caz emite un avertisment în timpul traducerii, pe care programatorul îl poate ignora.
Spre deosebire de „zahărul sintactic”, care extinde libertatea de exprimare a programatorului, „sarea sintactică” o restrânge, necesitând „fără motiv” să se scrie construcții lungi. Fișierul Jargon spune că „sarea de sintaxă este proastă pentru că crește tensiunea arterială a unui hacker”. Într-adevăr, la scrierea unor programe mici create și întreținute de o singură persoană, măsurile de precauție pot părea redundante, totuși, în dezvoltarea industrială a sistemelor software mari susținute de echipe mari de programatori, adesea, în plus, nu de cea mai înaltă calificare, „sarea sintactică” ajută să nu facă greșeli în dezvoltare și să înțeleagă mai eficient codul scris de alți dezvoltatori.
Exemple: