Tugev ja nõrk tüüpimine

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 teha vaiketüübiteisendusi. 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
1974. aastal 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.
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".

## Tugeva ja nõrga tüüpimise definitsioonid
Mitmetele keeledisaini valikutele on viidatud kui asitõendile "tugevast" või "nõrgast" tüüpimisest. Praktikas 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
Luca Cardelli artiklis "Typeful Programming" 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
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
Mõnes programmeerimiskeeles, näiteks Pythonis, ei eksisteeri staatilist tüübikontrolli. Mitmes sellises keeles on lihtne kirjutada programme, mille enamik staatilisi tüübikontrolle tagasi lükkaks. Näiteks, muutuja võib sisaldada kas numbrit või tõeväärtust "väär".

### Viidad
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.

### Vaiketüübiteisendus ja "tüübisõnamäng"
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."

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.

Näiteid keeltest, mis lubavad vaiketüü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

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 enamikku 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 see 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 ja sellega seotud kompilaatorid) kasutavad neid deklaratsioone koos tüübijäreldamisega, et lubada piiratud kompileerimise aegseid tüübikontrolle ja erinevaid optimeerimistehnikaid.

* Smalltalk, Perl, Ruby, Python ja Self on kõik tugevalt tüübitud sellest mõttes, et tüüpimisvead hoitakse ära käitamise ajal ja vaiketüü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.

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