Javascript:
>>> 1()
TypeError: 1 is not a function
Rubino:
>>> 1 + ""
String can't be coerced into Fixnum
Questi sono entrambi casi semplici di errore di tipo dinamico. Molte lingue, tra cui quasi tutte le lingue dinamiche, ma anche, ad es., C # e Java, eseguono il "tipo tagging". Cioè, i runtime di questi ambienti devono, in effetti, collegare una rappresentazione di un tipo a ogni oggetto. Questo è diverso rispetto alla tipizzazione statica perché i tag di tipo esistono in fase di esecuzione e in almeno i linguaggi dinamici e imperativi come Ruby e Javascript una variabile può puntare a oggetti diversi con tipi diversi.
Il runtime deve, per implementare la semantica della lingua, controllare continuamente questi tag tipo. Ad esempio, nell'esecuzione dell'operazione +
su due oggetti, questi linguaggi controllano i tag di tipo su entrambi gli oggetti per decidere cosa fare. Se entrambi gli oggetti sono contrassegnati come numerici, viene eseguita l'aggiunta (eventualmente dopo una conversione di tipo a un tipo numerico comune). Se entrambi gli oggetti sono contrassegnati come tag di tipo stringa, viene eseguita la concatenazione delle stringhe. (Quello che potrebbe esserti fatto braccetto è che Javascript eseguirà grandi quantità di conversioni di tipo runtime durante il normale funzionamento: sembra che non stia controllando i tag di tipo, perché non vengono generati errori di tipo, quando in realtà i tag di tipo sono essere controllato dappertutto per eseguire queste conversioni.)
Si noti che questo controllo del tag di tipo ha solo una vaga e per lo più fuorviante somiglianza con il controllo di tipo (statico). Il controllo statico del tipo controlla le proprietà dell'espressione prima del runtime mentre il controllo del tag di tipo controlla le proprietà del valore che l'espressione esprime in fase di esecuzione. Sia Ruby che Javascript eseguono il controllo del tag di tipo nel loro ambiente runtime di base (ad es. In +
, -
, invocazione funzione). Consentono inoltre all'utente di utilizzare la type-tag introspection . Cioè, consentono all'utente di verificare la tag di tipo di un valore in fase di runtime.
Actually, according to GoF, a type is simply a set of interface, so how can you "check" the type, other than whether it responds to a particular message?
Non ho familiarità con questa definizione, ma mi sembra fuorviante. Un tipo statico è un token che viene associato in base a una serie di regole di digitazione con espressioni in una lingua e viene utilizzato per definire quali espressioni sono semanticamente valide in quella lingua. Un "tipo dinamico" (o tag di tipo, come preferisco) è un valore che viene associato a oggetti nel runtime di una lingua. In un certo senso, entrambi sono legati alle interfacce. Nei linguaggi tipizzati staticamente, il tipo definisce quali espressioni può essere legalmente visualizzata un'espressione di quel tipo e quindi in tale misura determina un'interfaccia per quel tipo. Analogamente, i tag di tipo determinano, in parte, quali operazioni termineranno in un runtime "TypeError" prima ancora che l'operazione venga tentata.
Tuttavia, è fuorviante identificare il tipo / tag di tipo con la sua interfaccia nella maggior parte delle lingue dinamiche statiche. Essenzialmente tutti i linguaggi statici e dinamici sono in gran parte nomatamente e non strutturalmente tipizzati. Cioè, in un normale linguaggio tipizzato staticamente, se definisci un tipo YourCustomer
e definisco MyCustomer
, le espressioni dei due tipi non saranno intercambiabili. anche se le definizioni di YourCustomer
e MyCustomer
sono identiche fino alla denominazione. Allo stesso modo, se si definisce un oggetto Javascript con type-tag YourJSCustomer
e io definisco un oggetto Javascript con type-tag MyJSCustomer
, anche se questi due oggetti hanno le stesse proprietà e metodi altrimenti non saranno intercambiabili in faccia di introspezione con tag di tipo.
È vero che in molte lingue digitate dinamicamente, l'introspezione del tag di tipo non è sempre utilizzata e quindi YourJSCustomer
e MyJSCustomer
saranno intercambiabili in molti ambienti. Questo perché queste lingue consentono di sostituire o integrare il controllo del tag di tipo con il controllo degli attributi. Quindi, se chiami x.foo()
in JS, Ruby, Python, & c., Cercherà l'attributo .foo
sull'oggetto x
. Ciò consente l'eliminazione di alcuni, ma in genere non tutti, il controllo del tag di tipo.
Si noti che nelle lingue tipizzate staticamente con la tipizzazione strutturale , è possibile avere YourCustomer
e MyCustomer
intercambiabili nella maggior parte / tutti i contesti. Questo dà una sensazione linguistica molto più vicina a un linguaggio come Javascript o Ruby. Ti suggerisco di guardare TypeScript per questo, che aggiunge un sistema di tipi a Javascript.