Quali linguaggi di programmazione supportano l'inferenza di tipo dai nomi di variabili? [chiuso]

2

Quali linguaggi di programmazione supportano l'inferenza di tipo dai nomi di variabili?

Per "tipo di inferenza", intendo, ad esempio, in Swift, come se tu let x = 39 il compilatore sappia che x è un Integer , perché 39 è un numero intero.

Ora, in Swift è convenzionale usare la parola chiave is all'inizio delle variabili Boolean . Ad esempio let isCool = true . Tuttavia se facciamo let isCool = 0 , il compilatore dedurrà il tipo di isCool come Integer invece di Bool , anche se qualsiasi programmatore umano saprebbe che dovrebbe essere un Bool a causa della presenza di is all'inizio del nome della variabile.

Quindi, mi è venuto in mente, mi chiedo se ci sono dei linguaggi di programmazione in cui è possibile dare al compilatore un indizio per aiutarlo a dedurre il tipo utilizzando le parole chiave nel nome della variabile stessa? Qualcuno ha mai visto qualcosa del genere?

Nota a margine:

Questo non era destinato a essere una domanda sul merito di ciò, ma solo per quello che sai, la ragione per cui l'ho chiesto era perché pensavo che fosse qualcosa che potrebbe essere una caratteristica che potrebbe consentire un codice più pulito nell'integrazione webservice livelli, a causa della necessità di analizzare un sacco di JSON in variabili e linguaggi come Swift rendendo questo un dolore con tutta la loro sicurezza del tipo forzato.

Quindi ecco un esempio di come questo potrebbe migliorare alcuni codici in Swift.

Supponiamo che i clienti JSON siano alcuni dati provenienti da una risposta al servizio web. Se il server ha un bug, i contenuti potrebbero non essere i tipi che ci aspettiamo. Quindi un linguaggio di tipo strettamente sicuro come Swift 3 applica attualmente un codice simile al seguente:

    let customersJSON = "[{\"customerName\":\"Alice\",\"customerAge\":42},{\"customerName\":808,\"customerAge\":88}]".data(using: .utf8)!
    var customersArray: [Any]!
    do {
        customersArray = try JSONSerialization.jsonObject(with: customersJSON, options: JSONSerialization.ReadingOptions()) as? Array
    } 
    catch {
        print(error)
        return;
    }
    for customer in customersArray {
        guard let customerDict = customer as? [String:Any],
            let customerName = customerDict["customerName"] as? String,
            let customerAge = customerDict["customerAge"] as? Int 
            else {break}
        print("customerName: \(customerName), customerAge: \(customerAge)") 
    }

Nota che quando assegniamo dict["customerName"] a customerName , dobbiamo dire al compilatore che customerName dovrebbe essere un String con la sintassi as? String .

Naturalmente, gli esseri umani sanno che i nomi sono sempre degli archi; come programmatore mi sta solo seccando di doverlo dire sempre al compilatore, se per esempio, ho diverse cose come productName e itemName e discountName ecc. che devono essere gestite in vari gestori di risposta. Preferisco dire al compilatore una sola volta che qualsiasi variabile il cui nome termina in "Nome" è una stringa.

Preferirei piuttosto impostare una preferenza globale nella mia app, usando i modelli di corrispondenza regolare per dare al compilatore un suggerimento, come:

Infer ".*Array":[Any]!
Infer ".*Name":String
Infer ".*Age":Int
Infer ".*Dict":[String:Any]

Quindi possiamo fare:

    let customersJSON = "[{\"customerName\":\"Alice\",\"customerAge\":42},{\"customerName\":808,\"customerAge\":88}]".data(using: .utf8)!

    var customersArray
    do {
        customersArray = try JSONSerialization.jsonObject(with: customersJSON, options: JSONSerialization.ReadingOptions())
    } 
    catch {
        print(error)
        return;
    }
    for customer in customersArray {
        guard let customerDict = customer,
            let customerName = customerDict["customerName"],
            let customerAge = customerDict["customerAge"] 
            else {break}
        print("customerName: \(customerName), customerAge: \(customerAge)") 
    }

... e hanno ancora la sicurezza totale del tipo di Swift, senza tutta la bruttezza. Ora sembra più un codice di una lingua digitata in modo dinamico. Non sto dicendo che sia "migliore" in questo modo, ma penso che sia un codice più elegante e più leggibile. YMMV

    
posta CommaToast 08.11.2016 - 02:34
fonte

3 risposte

8

Le versioni molto iniziali di FORTRAN utilizzavano la prima lettera del nome della variabile per indicare il tipo, per i tipi di base INTEGER e REAL. La doppia precisione (real realistici a precisione estesa) doveva essere dichiarata esplicitamente.

Almeno FORTRAN IV, almeno alcune versioni di FORTRAN hanno consentito alle dichiarazioni esplicite di ignorare la regola della prima lettera.

FORTRAN 77 consentiva di specificare le proprie regole personali della prima lettera e di disabilitarle del tutto. (Esempio: IMPLICIT INTEGER (NONE))

Va detto che era generalmente accettato nella comunità informatica almeno nella metà degli anni '60 che le regole di tipo predefinite e le dichiarazioni di variabili implicite erano una pessima idea. Tony Hoare riferisce di aver timbrato le orecchie dal comitato ALGOL quando ha proposto tale modifica ad ALGOL. (Ha menzionato che questo era prima che la storia, probabilmente apocrifa, della sonda Venus perduta, a causa di un errore tipografico che tuttavia producesse un programma FORTRAN sintatticamente legale, fosse ampiamente conosciuta).

    
risposta data 08.11.2016 - 04:37
fonte
7

I've never seen anything like that, but wouldn't it be a cool feature to be able to set up some keywords to mean certain things, so that you could avoid repetitive boilerplate and have more readable code, to boot?

Mi dispiace, no. Questa non è una buona idea.

La dichiarazione delle variabili è un passo significativo, non "boilerplate".

Una caratteristica del buon design del linguaggio è che le dichiarazioni delle variabili devono essere esplicite. Essere in grado di usare variabili che non sono state dichiarate può fare un errore di battitura in un bug significativo, e inoltre ci possono essere problemi nascosti piuttosto problematici causati da collisioni nei nomi di variabili tra diversi ambiti.

Mentre ci sono alcuni linguaggi che consentono variabili senza dichiararli (Perl, Javascript, ecc.), questo è sconsigliato, tranne che per gli hacker / script rapidi e in genere le funzionalità linguistiche sono state aggiunte in seguito per disattivare questo comportamento.

Quindi, questo significa che anche nel tuo linguaggio teorico, le buone pratiche richiederebbero comunque una riga di dichiarazione per qualsiasi sviluppo significativo. Qualcosa del genere:

var intNum;

Non salva il codice rispetto a questo:

int num;

Danneggia invece di facilitare la leggibilità.

Motivi per cui non è necessario:

  • Il tipo di una variabile è molto spesso deselezionato dal contesto.
  • Il codice ben progettato avrà molti suggerimenti sul tipo di variabile.
    • La buona pratica consiste nel suddividere il codice in piccole funzioni, che (nella maggior parte delle lingue) hanno un prototipo che indica il tipo di argomenti.
    • Le variabili dovrebbero essere dichiarate il più vicino possibile al loro punto di utilizzo e le variabili globali dovrebbero essere evitate. Questo è importante per altri motivi e significa che una dichiarazione di variabile è spesso abbastanza vicina al codice su cui stai lavorando.
  • Le informazioni sul tipo sono anche facilmente disponibili negli strumenti di sviluppo.

Ragioni per le quali può causare più danni che benefici:

  • Aggiunge rumore al codice. Se hai una variabile x che viene usata 10 volte, essere costretti a chiamarlo intx invece aggiunge molte cose inutili al codice. E tutte le variabili dello stesso tipo ora sembrano simili, rendendo difficile distinguerle l'una dall'altra.
  • Rompe davvero i tipi più complessi. Questo schema sarebbe praticabile se tu avessi solo alcuni tipi di base come int, float, ecc. Ma nei linguaggi moderni (beh, in realtà anche in lingue antiche come C ), puoi avere tipi definiti dall'utente che sono molto più complessi. Quanto bene funziona questa idea con la programmazione orientata agli oggetti, dove il tipo di oggetto potrebbe essere DoohickyFrobulatorFactory ?
  • Inoltre non aiuta con puntatori / riferimenti. Un puntatore può essere usato per riferirsi a oggetti di più tipi. Mentre potresti chiamarlo ptrFoo , probabilmente questa non è tutta questa informazione utile. Ciò che è più significativo è quale tipo di oggetto sta puntando. Ma il sistema non aiuta in questo.
  • Rende più difficile modificare il tipo. Che cosa succede se decidi che il tuo int deve essere un long int o simile? Questo dovrebbe essere un cambiamento banale, ma è più complesso se devi rinominare la variabile.

Naturalmente, potresti già usare questa convenzione di denominazione se lo volessi (solo non forzato dal compilatore). In realtà è una convenzione di denominazione stabilita denominata Notazione ungherese ed era piuttosto popolare in un punto. Ma è ampiamente scoraggiato oggi. Vedi l'articolo collegato per ulteriori informazioni.

    
risposta data 08.11.2016 - 11:39
fonte
1

Fortran è già stato trattato quindi non dirò altro su di esso ....

Non conosco alcun linguaggio di programmazione che deduca un tipo basato sulla variabile o sul nome del parametro. Tuttavia ci sono molti standard di codifica che raccomandano come devono essere denominate variabili, metodi, classi ecc.

Puoi quindi utilizzare un controllo di stile per confermare se gli standard di denominazione sono stati mantenuti, quindi ricevere un avviso (o un errore) dal tuo sistema di build se l'uso lo ha.

let isCool = 0
    
risposta data 08.11.2016 - 17:03
fonte

Leggi altre domande sui tag