La notazione ungherese è una soluzione alternativa per le lingue con digitazione statica insufficientemente espressiva? [chiuso]


28

Nell'articolo di Eric Lippert Che succede con la notazione ungherese? , afferma che lo scopo della notazione ungherese (il tipo buono) è quello di

estendere il concetto di "tipo" per includere informazioni semantiche oltre alle informazioni sulla rappresentazione della memoria.

Un semplice esempio potrebbe essere il prefisso di una variabile che rappresenta una coordinata X con "x" e una variabile che rappresenta una coordinata Y con "y", indipendentemente dal fatto che tali variabili siano numeri interi o float o altro, in modo che quando si scrive accidentalmente xFoo + yBar, il codice sembra chiaramente sbagliato.

Ma ho anche letto del sistema di tipi di Haskell, e sembra che in Haskell si possa ottenere la stessa cosa (cioè "estendere il concetto di tipo per includere informazioni semantiche") usando tipi reali che il compilatore controllerà per te. Quindi nell'esempio sopra, xFoo + yBarin Haskell non verrebbe effettivamente compilato se il programma fosse stato progettato correttamente, poiché sarebbero stati dichiarati tipi incompatibili. In altre parole, sembra che il sistema di tipi di Haskell supporti effettivamente il controllo in fase di compilazione equivalente alla notazione ungherese

Quindi, la Notazione ungherese è solo un aiuto di banda per i linguaggi di programmazione i cui sistemi di tipi non possono codificare informazioni semantiche? O la Notazione ungherese offre qualcosa di diverso da quello che può offrire un sistema di tipo statico come quello di Haskell?

(Certo, sto usando Haskell come esempio. Sono sicuro che ci sono altre lingue con sistemi di tipo similmente espressivi (ricchi? Forti?), Sebbene non ne abbia mai trovato nessuno.)


Per essere chiari, io non parlando di annotare i nomi delle variabili con il dati di tipo, ma piuttosto con le informazioni sul significato della variabile nel contesto del programma. Ad esempio, una variabile può essere un numero intero o float o double o long o altro, ma forse il significato della variabile è che è una coordinata x relativa misurata in pollici. Questo è il tipo di informazioni di cui sto parlando sulla codifica tramite la Notazione ungherese (e tramite i tipi di Haskell).


Pascal - anche se se provi ad aggiungere un tipo XCood e YCoord che hai definito in Pascal riceverai solo un avviso del compilatore IIRC
mcottle

1
blog.moertel.com/articles/2006/10/18/… è un articolo su come fare qualcosa di molto simile alle "app ungheresi" nel sistema di tipi in Haskell.
Logan Capaldo,

1
F # ha anche questa caratteristica di stile.
Rangoric,

Questo è un link all'articolo molto carino (quello di moertel.com) che mostra esattamente il tipo di cosa a cui stavo pensando: usare il sistema dei tipi per trasformare le vulnerabilità della sicurezza dell'interpolazione di stringhe e simili in errori di compilazione. Grazie per il link
Ryan C. Thompson,

Penso che OO abbia raggiunto la notazione ungherese per la semantica, perché oggi probabilmente scriveresti: Foo.Position.X + Bar.Position.Y.
Pieter B,

Risposte:


27

Direi di si".

Come dici tu, lo scopo della notazione ungherese è codificare le informazioni nel nome che non possono essere codificate nel tipo. Tuttavia, ci sono fondamentalmente due casi:

  1. Questa informazione è importante.
  2. Questa informazione non è importante.

Cominciamo dal primo caso 2: se quell'informazione non è importante, allora la notazione ungherese è semplicemente un rumore superfluo.

Il caso più interessante è il numero 1, ma direi che se l'informazione è importante, dovrebbe essere controllata, cioè dovrebbe essere parte del tipo , non il nome .

Il che ci riporta alla citazione di Eric Lippert:

estendere il concetto di "tipo" per includere informazioni semantiche oltre alle informazioni sulla rappresentazione della memoria.

In realtà, non si tratta di "estendere il concetto di tipo", questo è il concetto di tipo! L' intero scopo dei tipi (come strumento di progettazione) è codificare le informazioni semantiche! La rappresentazione di archiviazione è un dettaglio di implementazione che di solito non appartiene affatto al tipo . (E in particolare in un linguaggio OO non può appartenere al tipo, poiché l'indipendenza della rappresentazione è uno dei prerequisiti principali per OO.)


C, dove la notazione ungherese era il più utilizzato AFAIK, non è tuttavia una lingua OO.
Péter Török,

4
@PéterTörök: OO è un modello di progettazione, non una caratteristica di una lingua, sebbene le lingue moderne siano progettate per renderlo semplice mentre C non lo è.
Jan Hudec,

3
@PéterTörök: ho scritto un sacco di codice orientato agli oggetti nella pianura C. So di cosa sto parlando.
Jan Hudec,

1
Mentre può essere vero che informazioni importanti dovrebbero essere incorporate nel tipo di una variabile piuttosto che nel suo nome, ci sono molte cose importanti che dovrebbero essere dette, ma quali sistemi di tipo non possono esprimere. Ad esempio, se S1è l'unico riferimento in qualsiasi parte dell'universo a un char[], il cui titolare può e lo cambierà ogni volta che lo desidera, ma non deve mai esporre a un codice esterno, ed S2è un riferimento a un char[]che nessuno dovrebbe mai cambiare, ma che può essere condiviso con oggetti che promettono di non cambiarlo, dovrebbero S1ed S2essere considerati semanticamente lo stesso "genere di cose"?
supercat,

1
@supercat - Stai descrivendo i tipi di unicità.
Jack,

9

L'intero scopo dei tipi (come strumento di progettazione) è codificare le informazioni semantiche!

Mi è piaciuta questa risposta e volevo dare seguito a questa risposta ...

Non so nulla di Haskell, ma puoi realizzare qualcosa di simile all'esempio di xFoo + yBarqualsiasi linguaggio che supporti una qualche forma di sicurezza del tipo come C, C ++ o Java. In C ++ puoi definire le classi XDir e YDir con operatori '+' sovraccarichi che accettano solo oggetti del loro stesso tipo. In C o Java, dovresti fare la tua aggiunta usando una funzione / metodo add () invece dell'operatore '+'.

Ho sempre visto la notazione ungherese utilizzata per le informazioni sul tipo, non per la semantica (tranne nella misura in cui la semantica potrebbe essere rappresentata dal tipo). Un modo conveniente per ricordare il tipo di una variabile nei giorni precedenti agli editor di programmazione "intelligenti" che visualizzano il tipo per te in un modo o nell'altro direttamente nell'editor.


Essere orientati agli oggetti non è né necessario né sufficiente affinché un linguaggio consenta xFoo + yBartipi definiti dall'utente, né è necessario l'aspetto OO del C ++ affinché quell'esempio funzioni.
Luc Danton,

Hai ragione non è OO, è un tipo di sicurezza. Ho modificato la mia risposta.
BHS,

Hmm. È un buon punto che potresti commettere xFoo + yBarun errore di compilazione (o almeno un errore di runtime) in quasi tutte le lingue. Tuttavia, la matematica con le classi XDir e YDir, ad esempio, in Java o C ++ sarebbe più lenta della matematica con numeri non elaborati? La mia comprensione è che in Haskell, i tipi vengono controllati al momento della compilazione, e quindi in fase di esecuzione, sarebbe solo matematica grezza senza controllo del tipo e quindi non più lenta dell'aggiunta di numeri regolari.
Ryan C. Thompson,

In C ++, il controllo del tipo verrebbe eseguito anche in fase di compilazione e la conversione e simili verranno ottimizzati nella maggior parte dei casi. Java non lo fa altrettanto, perché non consente il sovraccarico dell'operatore e simili - quindi non puoi considerare un XCoordinateint normale, ad esempio.
cHao,

5

Mi rendo conto che la frase "Notazione ungherese" ha significato qualcosa di diverso dall'originale , ma risponderò "no" alla domanda. La denominazione delle variabili con tipo semantico o computazionale non fa la stessa cosa della digitazione in stile SML o Haskell. Non è nemmeno un cerotto. Prendendo C come esempio, potresti nominare una variabile gpszTitle, ma quella variabile potrebbe non avere un ambito globale, potrebbe anche non costituire un punto per una stringa con terminazione nulla.

Penso che le più moderne notazioni ungheresi abbiano una divergenza ancora maggiore da un forte sistema di deduzione del tipo, perché mescolano informazioni "semantiche" (come "g" per globale o "f" per bandiera) con il tipo computazionale ("p" pointer ", i "numero intero, ecc. ecc.). Questo finisce per essere un disordinato pasticcio in cui i nomi delle variabili hanno solo una vaga somiglianza con il loro tipo computazionale (che cambia nel tempo) e tutti sembrano così simili che non è possibile utilizzare la" corrispondenza successiva "per trova una variabile in una particolare funzione - sono tutti uguali.


4

La notazione ungherese è stata inventata per BCPL, una lingua che non aveva affatto i tipi. O meglio, aveva esattamente un tipo di dati, la parola. Una parola potrebbe essere un puntatore o potrebbe essere un carattere o un valore booleano o un numero intero semplice a seconda di come l'hai usata. Ovviamente questo ha reso molto facile fare errori orribili come dereferenziare un personaggio. Quindi è stata inventata la notazione ungherese in modo che il programmatore potesse almeno eseguire il controllo manuale del tipo guardando il codice.

C, un discendente di BCPL, ha tipi distinti per numeri interi, puntatori, caratteri ecc. Ciò ha reso in qualche modo superflua la notazione ungherese di base (non era necessario codificare nel nome della variabile se era un int o un puntatore), ma la semantica oltre questo livello non può ancora essere espressa come tipi. Ciò ha portato alla distinzione tra ciò che è stato chiamato "Sistemi" e "App" ungherese. Non è stato necessario esprimere che una variabile era un int, ma è possibile utilizzare lettere di codice per indicare se int era un dire una coordinata x o y o un indice.

Linguaggi più moderni consentono definizioni di tipi personalizzati, il che significa che è possibile codificare i vincoli semantici nei tipi, piuttosto che nei nomi delle variabili. Ad esempio, un tipico linguaggio OO avrà tipi specifici per coppie di coordinate e aree, quindi si evita di aggiungere una coordinata x a una coordinata y.

Ad esempio, nel famoso articolo di Joels che elogia le app ungheresi, usa l'esempio del prefisso usper una stringa non sicura e sper una stringa sicura (codificata HTML), al fine di impedire l'iniezione HTML. Lo sviluppatore può prevenire errori di iniezione HTML semplicemente ispezionando attentamente il codice e assicurando che i prefissi variabili corrispondano. Il suo esempio è in VBScript, un linguaggio ormai obsoleto che inizialmente non consentiva le classi personalizzate. In un linguaggio moderno il problema può essere risolto con un tipo personalizzato, e in effetti questo è ciò che Asp.net fa con la HtmlStringclasse. In questo modo il compilatore troverà automaticamente l'errore, che è molto più sicuro che fare affidamento sul bulbo oculare umano. Quindi chiaramente una lingua con tipi personalizzati elimina la necessità di "App ungherese" in questo caso.


2

Sì, anche se molte lingue che hanno sistemi di tipi sufficientemente potenti presentano ancora un problema: l'espressività di nuovi tipi basati su / simili ai tipi esistenti.

cioè in molti linguaggi in cui potremmo usare il sistema dei tipi più non lo facciamo perché il sovraccarico di creare un nuovo tipo che è fondamentalmente lo stesso di un tipo esistente diverso dal nome e un paio di funzioni di conversione è troppo grande.

In sostanza abbiamo bisogno di una sorta di typedef fortemente tipizzati per uccidere la notazione ungherese in queste lingue (anche UoM in stile F # potrebbe farlo)


2

Ricorda, c'è stato un tempo in cui gli IDE non avevano suggerimenti popup per dirti che tipo di variabile è. C'è stato un tempo in cui gli IDE non capivano il codice che stavano modificando, quindi non si poteva passare facilmente dall'uso alla dichiarazione. C'è stato anche un tempo in cui non è stato possibile eseguire il refactoring di un nome di variabile senza passare manualmente attraverso l'intera base di codice, apportando la modifica manualmente e sperando di non averne perso uno. Non è possibile utilizzare la ricerca e la sostituzione perché la ricerca del cliente ti dà anche CustomerName ...

In quei giorni bui, era utile sapere che tipo di variabile era dove veniva usata. Se correttamente mantenuto (un GRANDE se a causa della mancanza di strumenti di refactoring) la notazione ungherese ti ha dato questo.

Il costo in questi giorni degli orribili nomi che produce è troppo alto, ma questa è una cosa relativamente recente. Esiste ancora molto codice che precede gli sviluppi dell'IDE che ho descritto.


1
Se non sbaglio, questa è un'altra risposta che si rivolge a un diverso tipo di notazione ungherese rispetto a quella richiesta dall'OP.
MatrixFrog,

2
Questa risposta descrive ciò che è stato chiamato "Sistemi ungherese", dove il prefisso indica il "tipo" a livello di lingua. La domanda è "App ungherese", dove la parola "tipo" non è stata fraintesa e significa il tipo semantico . I sistemi ungheresi sono condannati quasi universalmente in questi giorni (e giustamente, è una bastardizzazione del vero scopo della notaio ungherese). Le app ungheresi, tuttavia, possono essere una buona cosa.
cHao,

Gli editor in grado di cercare sCustomer senza raccogliere sCustomerName (vi ed emacs sono 2 esempi) esistono dagli anni '70.
Larry Coleman,

@Larry, forse, ma non sei riuscito a farli funzionare sui sistemi che stavo programmando negli anni '80
mcottle

@cHAo, No non lo è - il mio punto stava cercando di spiegare perché le persone mettessero le informazioni extra nei nomi delle variabili in generale. Ho accuratamente evitato di menzionare qualsiasi versione della notazione ungherese. Forse l'esempio che ho dato nella sezione "perché cercare e sostituire non funziona sul codice sorgente" ti appare come "Sistemi ungheresi" ma non era pensato per questo. Ho eliminato le "s" principali per evitare confusione.
moto

0

Corretta!

Al di fuori di linguaggi totalmente non tipizzati come Assembler, la notazione ungherese è superflua e fastidiosa. Dubbiamente, se si considera che la maggior parte degli IDE controlla la sicurezza del tipo mentre si digita.

I "i" "d" e "?" In più i prefissi rendono il codice meno leggibile e possono essere veramente fuorvianti, come quando un "cow-orker" cambia il tipo di iaSumsItem da Integer a Long ma non si preoccupa di riformattare il nome del campo.


9
La tua risposta suggerisce che non capisci la differenza tra l'originale, intelligente "App" ungherese e la stupida bastardizzazione chiamata "Sistemi" ungherese. Leggi joelonsoftware.com/articles/Wrong.html
Ryan Culpepper
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.