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