Likbez privind tipizarea în limbile de programare

Likbez privind tipizarea în limbile de programare

Vă recomandăm să citiți mai întâi o versiune scurtă a articolului și apoi, dacă aveți dorința și completați.

Versiune scurtă

Limbajele de programare prin tastare sunt împărțite în două tabere mari - tipărite și netupate (netăiate). Primul exemplu este C, Python, Scala, PHP și Lua, și al doilea limbaj de asamblare, Forth și Brainfuck.







  • Încărcare statică / dinamică. Staticul este determinat de faptul că tipurile finale de variabile și funcții sunt stabilite în etapa de compilare. Ie deja compilatorul este 100% sigur care tip este unde. În tastarea dinamică, toate tipurile se găsesc deja la momentul executării.
  • Tipărirea puternică / slabă (de asemenea, uneori, spuneți stricte / nu stricte). Difuzarea puternică se distinge prin faptul că limba nu permite amestecarea diferitelor tipuri în expresii și nu efectuează conversii implicite automate, de exemplu, nu puteți scăpa mult din șir. Limbile cu tastare slabă efectuează automat mai multe conversii implicite, chiar dacă poate exista o pierdere de precizie sau conversia este ambiguă.
  • Tastarea explicită / implicită. Limbile limitate în mod explicit diferă prin faptul că tipul de noi variabile / funcții / argumentele acestora trebuie specificat explicit. În consecință, limbile cu tastare implicită trec această sarcină la compilator / interpret.

    Cu toate acestea, nu există limbi cu greșeli statice și dinamice în același timp. Deși am alergat înainte, voi spune că aici minte - există într-adevăr, dar mai mult despre asta mai târziu.

    Versiune detaliată

    Dacă versiunea scurtă nu pare a fi suficient de bună. Nu e de mirare că am scris mai mult? Principalul lucru este că în versiunea scurtă a fost pur și simplu imposibil să se potrivească toate informațiile utile și interesante, iar informațiile detaliate vor fi probabil prea lungi pentru ca toată lumea să o citească fără a se încurca.

    Nu a fost scrisă

    În limbile de programare nedotate - toate entitățile sunt considerate pur și simplu secvențe de biți de diferite lungimi.

    dactilografiere netipizat este, de obicei, caracterizat printr-un nivel scăzut (limbaj de asamblare, Forth) și limbi ezoterice (brainfuck, HQ9, Piet). Cu toate acestea, ea, împreună cu neajunsurile, are anumite avantaje.

    avantaje
    • Vă permite să scrieți la cel mai mic nivel posibil, iar compilatorul / interpretul nu va interfera cu verificările de tip. Sunteți liber să efectuați orice operațiune pe orice tip de date.
    • Codul rezultat este de obicei mai eficient.
    • Transparența instrucțiunilor. Dacă cunoașteți limba, de obicei nu există nici o îndoială cu privire la ceea ce reprezintă un cod.
    deficiențe
    • Complexitatea. Deseori, este necesar să se reprezinte valori complexe, cum ar fi liste, șiruri sau structuri. Acest lucru poate cauza neplăceri.
    • Lipsa controalelor. Orice acțiune fără sens, de exemplu scăderea unui indicator la o matrice de la un simbol, va fi considerată perfect normală, care este plină de erori subtile.
    • Nivel scăzut de abstractizare. Lucrul cu orice tip de date complex nu este diferit de lucrul cu numere, ceea ce, desigur, va crea multe dificultăți.
    Tip de tastare greu de tip?

    Da, există. De exemplu, într-un limbaj de asamblare (pentru x86 / x86-64, alții nu știu) nu se poate asambla programul dacă încercați să descărcați registru cx (16 biți) de Rax registru de date (64 biți).

    mov cx, eax; eroare de timp de asamblare

    Deci, se pare că în Assemler există încă tastarea? Cred că aceste controale nu sunt suficiente. Și părerea ta, desigur, depinde doar de tine.

    Încrucișarea statică și dinamică

    Likbez privind tipizarea în limbile de programare

    Principalul lucru care distinge între tastarea statică (statică) și dinamică (dinamică) este că toate verificările de tip sunt efectuate în etapa de compilare și nu în faza de execuție.

    Pentru unii oameni, se poate părea că tastarea statică este prea limitată (de fapt este, dar aceasta a fost mult timp eliminată cu ajutorul unor tehnici). Pentru unii, că limbile dinamice scrise sunt un joc cu foc, dar ce caracteristici le disting? Ambele specii au o șansă de existență? Dacă nu, de ce multe limbi statice și dinamice au fost tipărite?

    Beneficiile tipăririi statice
    • Verificările de tip apar doar o singură dată - în etapa de compilare. Și aceasta înseamnă că nu va trebui să aflăm în mod constant dacă încercăm să împărțim un număr într-un șir (și fie să emită o eroare sau să efectuăm o conversie).
    • Viteza execuției. Din punctul anterior, este clar că limbile statice tipărite sunt aproape întotdeauna mai rapide decât limbile dinamice tipărite.
    • În anumite condiții suplimentare, vă permite să detectați eventualele erori deja în etapa de compilare.
    Avantajele tastării dinamice
    • Simplitatea creării colecțiilor universale - grămezi de toate și toate (rareori există o astfel de necesitate, dar atunci când există o tipificare dinamică va câștiga).
    • Comoditatea de a descrie algoritmi generalizați (de exemplu, sortarea unui matrice care va funcționa nu numai pe lista de numere întregi, ci și pe lista numerelor reale și chiar pe lista de rânduri).
    • Ușor de învățat - limbile cu tastare dinamică sunt de obicei foarte bune pentru a începe programarea.

    Likbez privind tipizarea în limbile de programare

    Programare generalizată

    Ei bine, argumentul cel mai important pentru tastarea dinamică este comoditatea de a descrie algoritmi generalizați. Să ne imaginăm problema - avem nevoie de o funcție pentru a căuta prin mai multe tablouri (sau liste) - printr-o serie de numere întregi, printr-o serie de numere reale și printr-o serie de caractere.

    Cum o vom rezolva? Rezolvăm acest lucru în 3 limbi diferite: una cu tastare dinamică și două cu statică.

    Algoritmul de căutare Voi lua una dintre cele mai simple - bust. Funcția va prelua elementul, matricea (sau lista) și va returna indexul elementului sau, dacă elementul nu este găsit - (-1).

    Soluție dinamică (Python):

    După cum puteți vedea, totul este simplu și nu există probleme cu faptul că lista poate conține cel puțin numere, chiar liste, deși nu există alte matrice. Foarte bine. Să mergem mai departe - vom rezolva aceeași sarcină în Si!

    Soluție statică (C):

    Ei bine, fiecare funcție este asemănătoare cu versiunea Python, dar de ce există trei? A pierdut programarea statică?

    Și da, și nu. Există mai multe tehnici de programare, dintre care vom lua în considerare acum. Se numește programare generală, iar limba C ++ o susține bine. Să aruncăm o privire la noua versiune:







    Soluție statică (programare generală, C ++):

    Bine! Acest lucru nu pare mult mai complicat decât versiunea Python și nu trebuie să scrie prea mult. În plus, avem o implementare pentru toate rețelele, și nu doar pentru 3, necesare pentru rezolvarea problemei!

    Această versiune pare să fie exact ceea ce aveți nevoie - obținem atât avantajele tipăririi statice, cât și unele avantaje ale tastării dinamice.

    Este minunat că acest lucru este în general posibil, dar poate fi chiar mai bun. În primul rând, programarea generală poate fi mai convenabilă și mai frumoasă (de exemplu, în limba Haskell). În al doilea rând, pe lângă programarea generală, puteți aplica polimorfismul (rezultatul va fi mai rău), funcțiile de supraîncărcare (în mod similar) sau macrocomenzile.

    Statică în dinamică

    De asemenea, trebuie menționat faptul că multe limbi statice permit utilizarea de tipărire dinamică, de exemplu:

    • C # acceptă dinamicul de tip pseudo.
    • F # acceptă zahăr sintactic sub forma unui operator. pe baza căruia poate fi implementată o imitație de tipificare dinamică.
    • Haskell - tastarea dinamică este furnizată de modulul Data.Dynamic.
    • Delphi - prin intermediul unui varianta de tip special.

    De asemenea, unele limbi tipizate dinamic vă permit să profitați de scrierea statică:

    • Declarații de tip comun Lisp.
    • Perl este de la versiunea 5.6, destul de limitat.

    Deci, mergem mai departe?

    Tiparerea puternică și slabă

    Likbez privind tipizarea în limbile de programare

    Limbile cu tastare puternică nu vă permit să amestecați entități de diferite tipuri în expresii și nu efectuați conversii automate. De asemenea, ele sunt numite "limbi cu tastare strictă". Termenul englezesc pentru aceasta este o tastare puternică.

    Tipurile de limbaj slab tipărite, dimpotrivă, contribuie în orice mod la programatorul care amestecă diferite tipuri într-o singură expresie, iar compilatorul însuși va conduce totul la un singur tip. Ele sunt, de asemenea, numite "limbi cu tastare non-strictă". Termenul englezesc pentru aceasta este tastarea slabă.

    Formarea slabă este deseori confundată cu dinamica, ceea ce este complet greșit. O limbă introdusă dinamic poate fi slabă și puternic introdusă.

    Cu toate acestea, puțini oameni acordă importanță rigurozității introducerii textului. Se spune adesea că dacă o limbă este tipărită static, atunci veți putea prinde multe erori potențiale la compilare. Te mint!

    Limba trebuie să aibă, de asemenea, o tastare puternică. Într-adevăr, în cazul în care, în loc de un mesaj de eroare, compilatorul va adăuga doar la numărul de linii, sau mai rău încă, scade una din cealaltă matrice, pe care simțim că toate tipurile de „test“ va fi la momentul compilarii? Așa - tastarea slabă statică este chiar mai rea decât o tastare dinamică puternică! (Ei bine, aceasta este opinia mea)

    Deci, ce tipaj slab nu are niciun avantaj? Poate așa arăta, dar, în ciuda faptului că sunt un susținător puternic al tastării puternice, trebuie să fiu de acord că și cel slab are avantaje.

    Vrei să știi ce?

    Avantajele tiparului puternic
    • Fiabilitate - primiți o excepție sau o eroare de compilare, în loc de comportament greșit.
    • Viteza - în loc de schimbări ascunse, care pot fi destul de costisitoare, puternic tastat trebuie să le scrie în mod clar ceea ce face un programator, cel puțin știu că această bucată de cod poate fi lent.
    • Înțelegerea a programului - din nou, la fel, în loc de tipul implicit, programatorul scrie tot ceea ce el însuși, și, prin urmare, despre înțelegerea că șirul de comparație și numărul nu este auto-altul și nu în magie.
    • Cu siguranță - când scrieți conversiile manual, știi exact ce convertiți și în ce. De asemenea, veți înțelege întotdeauna că astfel de transformări pot duce la pierderea preciziei și rezultate incorecte.
    Avantajele tastării slabe
    • Convenabilitatea utilizării expresiilor mixte (de exemplu, din întregi și numere reale).
    • Abstractarea de la tastarea și concentrarea asupra sarcinii.
    • Brevetarea înregistrării.

    Bine, am rezolvat-o, se pare că tastarea slabă are și avantaje! Și există modalități de a transfera avantajele slabei tastări la puternice?

    Se pare că există chiar și două.

    Conversie de tip implicită, în situații cu valoare unică și fără pierderi de date

    Ugh ... E un punct destul de lung. Permiteți-mi să o reduc și mai mult la o "conversie implicită limitată" Deci, ce este exact o situație lipsită de ambiguitate și o pierdere de date?

    O situație unică, aceasta este o transformare sau o operațiune în care esența este ușor de înțeles. De exemplu, adăugarea a două numere este o situație neechivocă. O transformare a șirului - nu (probabil va crea o serie de element poate matrice, cu un astfel de lung, umplut cu elementele implicite, și, eventual, numărul este convertit într-un șir și apoi într-o matrice de caractere).

    Pierderea datelor este chiar mai ușoară. Dacă vom converti numărul real de 3,5 în ansamblu - pierdem o bucată de date (de fapt, această operațiune este încă controversată - ??? Cum va fi rotunjită până la o mai mică îndepărtând partea fracționară?).

    Transformările în situații ambigue și transformările cu pierderi de date sunt foarte, foarte rele. Nimic mai rău în programare.

    Dacă nu mă credeți, învățați limba PL / I sau chiar căutați specificația sa. Are reguli pentru conversia între TOATE tipurile de date! Doar naibii!

    Bine, să ne amintim de o conversie implicită limitată. Există astfel de limbi? Da, de exemplu, în Pascal puteți converti un număr întreg la un număr real, dar nu invers. De asemenea, există mecanisme similare în C #, Groovy și Common Lisp.

    Bine, am spus că există și un alt mod de a obține câteva idei de scriere slabă într-o limbă puternică. Și da, se numește polimorfism constructor.

    O voi explica cu exemplul minunatului limbaj Haskell.

    Constructorii constructori polimorfici au apărut ca urmare a observării faptului că sunt necesare conversii implicite în condiții de siguranță, în condiții de siguranță, atunci când se utilizează literali numerici.

    De exemplu, în expresia pi + 1. Nu vreau să scriu pi + 1.0 sau pi + float (1). Vreau să scriu doar pi + 1!

    Și acest lucru se face în Haskell, datorită faptului că literalul 1 nu are un tip specific. Nu este nici intreg, nici material, nici complex. E doar un număr!

    Ca urmare, atunci când scriem o sumă simplă a funcției x y. Înmulțește toate numerele între x și y (în trepte de 1), vom obține mai multe versiuni - sumă pentru întreg, pentru suma reală, suma pentru rațională, suma pentru numere complexe, chiar și suma tuturor tipurilor numerice pe care le definiți.

    Desigur, această metodă este salvată numai atunci când se utilizează expresii mixte cu litere numerice, iar acesta este doar vârful aisbergului.

    Bine, vom continua?

    Tastarea explicită și implicită

    Likbez privind tipizarea în limbile de programare

    O limbă cu tastare explicită presupune că programatorul trebuie să specifice tipurile de toate variabilele și funcțiile pe care le declară. Termenul englezesc pentru aceasta este tastarea explicită.

    O limbă cu scriere implicită, pe de altă parte, sugerează că uitați de tipuri și transferați sarcina de inferență de tip la un compilator sau interpret. Termenul englezesc pentru aceasta este tastarea implicită.

    La început, puteți decide că scrierea implicită este echivalentă cu tastarea dinamică și explicită - statică, dar vom vedea mai târziu că nu este cazul.

    Există avantaje pentru fiecare specie și, din nou, există combinații între acestea și dacă există limbi cu suport pentru ambele metode?

    Avantajele tastării explicite
    • Prezența fiecărei funcții de semnătură (de exemplu, int add (int, int)) face posibilă determinarea fără probleme a funcției.
    • Programatorul scrie imediat ce tipuri de valori pot fi stocate într-o anumită variabilă, ceea ce elimină necesitatea de a-și aminti.
    Avantaje ale tastării implicite
    • Reducerea intrării - add add (x, y) este cu mult mai mică decât int add (int x, int y).
    • Rezistența la schimbare. De exemplu, dacă într-o funcție o variabilă temporară era de același tip ca și argumentul de intrare, atunci într-o limbă scrisă în mod explicit, schimbarea tipului argumentului de intrare va trebui de asemenea să schimbe tipul variabilei temporare.

    Ei bine, este clar că ambele abordări au atât avantaje cât și dezavantaje (și care a așteptat ceva încă?), Deci să căutăm modalități de a combina aceste două abordări!

    Tastarea explicită pentru alegere

    Există limbi cu tastare implicită în mod implicit și abilitatea de a specifica tipul de valori, dacă este necesar. Traducătorul va tipări automat acest tip de expresie. O astfel de limbă este Haskell, să dăm un exemplu simplu, pentru claritate:

    Notă: intenționez să folosesc o funcție necumpată și intenționează, de asemenea, să scriu o semnătură privată în locul unei adăugări mai generale. (Num a) -> a -> a -> a. deoarece Am vrut să arăt ideea, fără a explica sintaxa lui Haskell.

    Hmm. După cum vedem, este foarte frumoasă și scurtă. Înregistrarea funcției are doar 18 caractere pe o singură linie, inclusiv spații!

    Totuși, ieșirea automată este un lucru destul de complicat, și chiar într-un limbaj atât de abrupt ca Haskell, uneori eșuează. (un exemplu de care este restricția unui monomorfism)

    Există limbi cu tastare implicită explicită și implicită - dacă este necesar? joc
    echno.

    Tastarea implicită prin alegere

    Noul limbaj standard de C ++ numit C ++ 11 (denumite anterior C ++ 0x), a fost introdus cuvântul cheie auto, prin care puteți forța compilator pentru a deduce tipul bazată pe context:

    Nu-i rău. Dar înregistrarea nu a fost redusă mult. Să ne uităm la exemplu cu iteratori (dacă nu înțelegeți, nu vă temeți, principalul lucru este că înregistrarea datorată producției automate este mult redusă):

    Wow! Iată reducerea. Bine, dar este posibil să faci ceva în spiritul lui Haskell, unde tipul valorii returnate va depinde de tipurile de argumente?

    Și din nou, răspunsul este da, datorită cuvântului cheie decltype în combinație cu auto:

    Se poate părea că această formă de scriere nu este foarte bun, dar în combinație cu programarea generică (templates / generice) tipizarea implicite sau inferenta automată poate face minuni.

    Unele limbi de programare pentru această clasificare

    concluzie

    Link-uri utile







    Articole similare

    Trimiteți-le prietenilor: