Tugev ja nõrk tüüpimine

Allikas: Vikipeedia
(Ümber suunatud leheküljelt Range tüüpsus)
Jump to navigation Jump to search

Programmeerimises klassifitseeritakse programmeerimiskeeli kõnekeelselt selle põhjal, kas keele tüübisüsteem teeb sellest tugeva või nõrga tüüpsusega keele. Nendel terminitel puudub täpne definitsioon, aga üldiselt on tugevalt tüübitud keelel rangemad tüüpimise reeglid ja see genereerib suurema tõenäosusega vea või keeldub kompileerimast, kui funktsioonile antud muutuja ei ole oodatud tüüpi. Teisalt, nõrgalt tüübitud keelel on vabamalt sõnastatud tüüpimise reeglid, mis võib tekitada ootamatuid tulemusi või teostada vaikimisi tüübiteisendusi.[1] Teistsugune, kuid seotud mõiste on peidetud tüüpimine, mis viitab tüübisüsteemile, kus tüübid on seotud väärtuste, mitte muutujatega. Selline tüüpimine nõuab tihti käitamisaegset tüübikontrolli.

Ajalugu[muuda | muuda lähteteksti]

Aastal 1974 defineerisid Barbara Liskov ja Stephen Zilles tugevalt tüübitud keele kui sellise, kus kutsuvast funktsioonist väljakutsutavasse funktsiooni saadetud muutuja peab tüübiliselt kattuma väljakutsutavas funktsioonis märgitud muutuja tüübiga.[2] Aastal 1977 kirjutas K. Jackson "Tugevalt tüübitud keeles on igal muutujal oma tüüp ja iga protsess annab oma suhtlusnõuetest teada nende tüüpide raames".[3]

Tugeva ja nõrga tüüpimise definitsioonid[muuda | muuda lähteteksti]

Mitmetele keeledisaini valikutele on viidatud kui asitõendile „tugevast“ või „nõrgast“ tüüpimisest. Tegelikkuses mõistetakse mitmeid nendest valikutest tüübiohutuse, mäluohutuse, staatilise tüübikontrolli ja dünaamilise tüübikontrolli puudumise või olemasoluna. Tugev tüüpimine viitab enamasti programmeerimiskeelte tüüpide kasutamisele eesmärgiga püüda koodi invariante, veenduda selle korrektsuses ja välistada teatud tüüpi programmeerimisvigu. Selle saavutamiseks kasutatakse mitmeid tugevalt tüüpimise võtteid.

Staatiline tüübikontroll[muuda | muuda lähteteksti]

Luca Cardelli artiklis „Typeful Programming“[4] kirjeldatakse „tugevat tüübisüsteemi“ kui süsteemi, milles ei ole võimalikud kontrollimata käitusaegsed tüübivead. Teistes tekstides viidatakse kontrollimata käitusaegsetele tüübivigadele kui turvalisusele või tüübi turvalisusele.

Sildistamata ühend[muuda | muuda lähteteksti]

Mõned programmeerimiskeeled, nagu näiteks C++, toetavad sildistamata ühendeid, mis lubavad ühte tüüpi väärtust vaadelda kui teist tüüpi väärtust.

Dünaamiline tüübikontroll[muuda | muuda lähteteksti]

Mõndades programmeerimiskeeltes, nagu näiteks Pythonis, ei eksisteeri staatilist tüübi kontrolli. Mitmetes sellistes keeltes on lihtne kirjutada programme, mille enamik staatilisi tüübi kontrolle tagasi lükkaks. Näiteks, muutuja võib sisaldada kas numbrit või tõeväärtust „väär“.

Viidad[muuda | muuda lähteteksti]

Mõningad programmeerimiskeeled, näiteks C, kohtlevad viitu kui numbrilisi väärtusi ja lubavad kasutajal nendega teha aritmeetilisi operatsioone. Nendest keeltest räägitakse kui nõrgalt tüübitud keeltest, kuna viida aritmeetikat saab kasutada keele tüübisüsteemist mööda minemiseks.

Vaikimisi tüübiteisendus ja "tüübisõnamäng"[muuda | muuda lähteteksti]

Mõned programmeerimiskeeled lihtsustavad üht tüüpi väärtuse teist tüüpi väärtusena kasutamist. Sellele viidatakse mõnikord kui nõrgale tüüpimisele.

Näiteks Aahz Maruch pakub: „Muundus toimub, kui staatiliselt tüübitud keelel kasutatakse keele süntaktilisi funktsioone, et sundida ühe tüübi kasutamist teise tüübina (näiteks C-s void* laialt levinud kasutus). Muundus on tavaliselt nõrga tüüpimise sümptom. Teisendamine aga loob sobivat tüüpi uue objekti.“[5]

Teise näitena kirjeldab GNU kompilaatorite kollektsioon seda kui tüübisõnamängu ja hoiatab, et see lõhub ära range aliase omistamise. Thiago Macieira arutleb mitmete probleemide üle, mis võivad tekkida, kui tüübisõnamäng paneb kompilaatori tegema ebavajalikku optimeerimist.[6]

Näiteid keeltest, mis lubavad vaikimisi tüübiümberarvestamist tüübiohutul moel, on mitmeid. Nii C++ ja C# lubavad programmidel defineerida operaatoreid semantiliselt tähenduslikul moel väärtuste ümberarvestamiseks ühest tüübist teiseks. Kui C++ kompilaator kohtab sellist ümberarvestust, kohtleb ta operatsiooni kui funktsiooni väljakutset. Vastandiks on C-keel, kus väärtuse ümberarvestamine void* tüübiks on kompilaatorile nähtamatu ohtlik operatsioon.

Erinevused programmeerimiskeelte tüüpimises[muuda | muuda lähteteksti]

Siinkohal tuleb tähele panna, et osad käsitletud definitsioonidest on vastuolulised, samas kui teised on vaid ideeliselt iseseisvad. Sellele lisaks on veel lisapiirangutega erijuhud vabamatest definitsioonidest. Kuna määratlused erinevad omavahel palju, on võimalik enamikke programmeerimiskeeli kutsuda nii tugevalt kui ka nõrgalt tüübituteks.

Visual Basicu näol on tegu hübriidkeelega. Selles keeles on võimalik kasutada muutujaid millel on kindel tüüp, aga on ka võimalik luua "Variant" andmetüüpi muutuja, mis suudab talletada infot ükskõik millise tüübi kohta. Selle vaikimisi sooritatud tüübimuutused on üpriski vabad, näiteks on võimalik summeerida sõne variante ja saadud tulemus saata täisarv tüüpi muutujale.

Assemblerkeel ja Forth on ilma tüübita. Mitte mingit tüübikontrolli ei toimu ja programmeerija ülesandeks on kindlustada, et funktsioonidele antavad andmed on õiget tüüpi. Kui tüübimuutmine on vajalik, siis tuleb seda spetsiifliselt välja kutsuda.

Standard ML, F#, OCami, Haskell ja Rust on staatilise tüübikontrolliga, aga kompilaator järeldab enamikule väärtustele automaatselt täpse tüübi.

Lispi keelteperekond on kõik tugevalt tüübitud selles suhtes, et tüüpimise vead hoitakse ära käitamise ajal. Mõned Lispi versioonid nagu Common Lisp või Clojure toetavad tüübideklaratsiooni erinevaid vorme ja mõned kompilaatorid (CMUCL[7] ja sellega seotud kompilaatorid) kasutavad neid deklaratsioone koos tüübijäreldamisega, et lubada piiratud kompileerimise aegseid tüübikontrolle ja erinevaid optimeerimistehnikaid.[8]

Smalltalk, Perl, Ruby, Python ja Self on kõik tugevalt tüübitud sellest mõttes, et tüüpimisvead hoitakse ära käitamise ajal ja vaikimisi tüübimuutusi tehakse vähe. Seevastu aga ei kasuta need keeled staatilist tüübikontrolli, mis tähendab, et kompilaator ei kontrolli ega sunni peale tüübipiirangute reegleid. Kasutatakse terminit "pardi tüüpimine", et kirjeldada dünaamilise tüüpimise paradigmat, mida sellesse gruppi kuuluvad keeled kasutavad.

Java, Pascal, Ada ja C kõik nõuavad, et muutujatel oleks kuulutatud tüüp, ja toetavad aritmeetiliste väärtuste muutmist teistesse aritmeetilistesse tüüpidesse läbi spetsiifilise tüübimuutuse välja kutsumise. Tihti väidetakse, et Java, C#, Ada ja Pascal on tugevamalt tüübitud kui C, kuna erinevalt näiteks Javast ja Pascalist toetab C rohkem vaikeväärtuste muutmist, lisaks lubab C ka viitade väärtusi otse kasutada. Javat võib pidada tugevamalt tüübituks kui Pascalit, kuna staatilisest tüübist hoidumise meetodeid kontrollib Javas Java virtuaalmasina tüübisüsteem. C# ja VB.NET sarnanevad selles suhtes Javaga, kuid neis mõlemas on võimalik dünaamiline tüübikontroll välja lülitada. Pascali tüübisüsteem aga on kohati liiga tugev, kuna näiteks massiivi või sõne pikkus on tüübi osaks, mis muudab programmeerimise keerukamaks.[9]

Nendel põhjustel kasutavad autorid, kes tahavad üheselt mõistetavalt kirjutada tüübisüsteemidest, tihti termini „tugevalt tüübitus“ asemel täpsemaid termineid, näiteks „tüübi turvalisus“.

Viited[muuda | muuda lähteteksti]

  1. "CS1130. Transition to OO programming. – Spring 2012 --self-paced version". Cornell University, Department of Computer Science. 2005. Originaali arhiivikoopia seisuga 2005. Vaadatud 2015-11-23. 
  2. Liskov, B; Zilles, S (1974). "Programming with abstract data types". ACM SIGPLAN Notices 9: 50–59. doi:10.1145/942572.807045. 
  3. Jackson, K. (1977). "Parallel processing and modular software construction". Design and Implementation of Programming Languages. Lecture Notes in Computer Science 54. pp. 436–443. ISBN 3-540-08360-X. doi:10.1007/BFb0021435. 
  4. Luca Cardelli, "Typeful programming"
  5. Aahz. "Typing: Strong vs. Weak, Static vs. Dynamic". 
  6. "Type-punning and strict-aliasing - Qt Blog". Qt Blog. 
  7. "CMUCL User's Manual: The Compiler". 
  8. "CLHS: Chapter 4". 
  9. InfoWorld.