Perché la semantica e i sistemi di tipi sono così importanti?

2

Ho sentito dire che la semantica e i sistemi di scrittura sono molto importanti per tutti i programmatori! Ma io perché sono così importanti? Non capisco. Forse sono imortanti solo per teorici e sviluppatori di compilatori?

Nella mia pratica non penso mai alla semantica e alla teoria dei tipi. Per quanto mi riguarda è sufficiente sapere che la semantica definisce il significato della sintassi. Quando scrivo + so solo che è l'operazione di aggiunta. Ed è abbastanza per me.

Quindi, voglio descrivere le mie opinioni sui sistemi di tipi. Inoltre, quando scrivo int i; , so che int è un numero intero ed è abbastanza per me.

Un altro caso: è importante sapere quale sia la differenza tra i sistemi di tipo statico e dinamico, debole e strong.

Dimmi, per favore, ci sono dei benefici pratici dalla conoscenza della semantica e dei sistemi di tipi?

    
posta Александр Елизаров 25.01.2016 - 10:53
fonte

2 risposte

17

Differenze semantiche secondarie

Considera questo semplice programma:

i = 1000'000'000
j = i * i

Questa operazione può comportarsi in modo molto diverso a seconda della semantica degli interi nella tua lingua:

  1. Alcune lingue passeranno a grandi numeri interi producendo il risultato corretto ( 1000'000'000'000'000'000 ), ma prestazioni degradanti (ad es. python)
  2. Alcune lingue passeranno senza problemi ai float, producendo un risultato approssimativo (ad esempio javascript e php)
  3. Alcune lingue generano un errore perché il risultato non si adatta a un intero a 32 bit (ad esempio C # con aritmetica selezionata attivata)
  4. Alcune lingue si avvolgeranno (ad esempio C # con aritmetica controllata disattivata, restituisce -1486618624 ). Il preciso comportamento di avvolgimento può variare a seconda delle dimensioni del tipo intero e della rappresentazione del segno (C # utilizza il complemento a due)
  5. Alcune lingue invocheranno un comportamento non definito (ad esempio C e C ++)
  6. Alcune lingue considereranno il letterale firmato, altri come non firmati

Differenze abbastanza grandi per qualcosa di semplice come moltiplicare due interi.

Oppure considera il caso in cui scrivi 1 + "1a" .

  1. Alcune lingue produrranno un errore di compilazione, chiedendoti di chiarire cosa intendevi.
  2. Alcune lingue produrranno un errore di runtime perché non puoi aggiungere interi e stringhe
  3. Alcune lingue tenteranno di analizzare la stringa come numero e generare un errore perché "1a" non è un numero decimale valido
  4. Alcune lingue analizzeranno correttamente la stringa, ad es. perché smettono di analizzare la prima cifra non
  5. Alcune lingue trattano entrambe come stringa e le concatenano.
  6. C tratterà "1a" come puntatore al char ed eseguirà l'aritmetica del puntatore, restituendo "a" .

Espressività del sistema tipo

Le cose diventano più interessanti una volta considerati i tipi complessi.

Diversi tipi di sistemi ti consentono di esprimere idee diverse elegantemente. Catturano errori diversi durante la compilazione o il runtime. Ti restringono in modi diversi. Richiedono diversi sforzi per imparare.

Dato che ogni programmatore e designer di linguaggi pesa in modo diverso su questi obiettivi (o non conosce nemmeno i vantaggi di alcuni di essi) otteniamo un sacco di lingue diverse.

  • C non ha un modo conveniente per scrivere un contenitore che funzioni con diversi tipi di elementi. C ++ ha template molto potenti, ma aggiungono molta complessità al linguaggio.
  • Go e Java supportano entrambe le interfacce. In Java la classe ha bisogno di implementare esplicitamente un'interfaccia, in Vai un tipo implementa implicitamente tutte le interfacce che corrispondono ai suoi membri. L'approccio Go consente al consumatore di definire le interfacce che soddisfano i suoi requisiti, ma può produrre false corrispondenze quando un membro ha lo stesso nome, ma un significato diverso.
  • Immutabilità semplifica il ragionamento sul codice e abilita le istanze di condivisione, ma può rendere scomodo la manipolazione dei dati.
  • La tipizzazione statica cattura molti errori in fase di compilazione. Ma catturare più errori aumenta lo sforzo richiesto per soddisfare il compilatore. A seconda di come si esprimono i vincoli di tempo di compilazione, si verificano errori diversi. Siamo sempre alla ricerca di nuovi sistemi di tipi che trovano più errori o richiedono meno sforzi.
  • Rust ha un sistema di tipi che può provare che nessun thread modificherà un oggetto mutabile allo stesso tempo. Ma in cambio richiede un meticoloso monitoraggio della proprietà, che molti programmatori considereranno troppo scomodo.
  • Ci sono molte caratteristiche che un linguaggio può offrire, come oggetti, ereditarietà multipla, distruzione deterministica, sicurezza della memoria, un GC, unioni discriminanti, funzioni di ordine superiore, contenitori / algoritmi generici, sovraccarico dell'operatore.

    Ognuno è utile in alcune situazioni, ma è necessario ponderarlo sulla complessità del linguaggio e quindi sullo sforzo di apprenderlo. Alcune funzionalità sono addirittura incompatibili o almeno interagiscono male tra loro.

risposta data 25.01.2016 - 11:15
fonte
5

When I write + I just know that it is the addition operation.

E come lo sai? Perché la semantica del linguaggio lo dice!

A proposito, non è nemmeno universalmente vero. Ad esempio, per String s in Java, + è non addizione, ma concatenazione!

when I write int i;, I know that int is an integer and it is enough for me.

E come fai a sapere cos'è un intero ? Il sistema di tipo ti dice!

A proposito, che anche non è universalmente vero. Ad esempio, in Java, int è non un numero intero ma piuttosto un membro dell'anello modulo ℤ 2 32 !

it is important to know what the difference beetwen static and dynamic, weak and strong type systems.

Quindi, tu dici che i sistemi di tipo sono importanti, ma poi chiedi se sono importanti?

    
risposta data 25.01.2016 - 11:24
fonte

Leggi altre domande sui tag