Ultimamente sono diventato sempre più frustrato che nella maggior parte dei linguaggi di programmazione moderni con cui ho lavorato (C / C ++, C #, F #, Ruby, Python, JS e altro) c'è molto poco, se non nessuno, supporto linguistico per determinare cosa farà effettivamente una subroutine.
Considera il seguente semplice pseudo-codice:
var x = DoSomethingWith(y);
Come faccio a determinare quale sarà la chiamata a DoSomethingWith (y) ? Muterà y , o restituirà una copia di y ? Dipende dallo stato globale o locale, o dipende solo da y ? Cambierà lo stato globale o locale? In che modo la chiusura influisce sull'esito della chiamata?
In tutte le lingue che ho incontrato, quasi nessuna di queste domande può essere risolta semplicemente guardando la firma della subroutine, e non c'è quasi mai alcun supporto in fase di compilazione o di runtime. Solitamente, l'unico modo è affidarsi all'autore dell'API e sperare che la documentazione e / o le convenzioni di denominazione rivelino ciò che effettivamente farà la subroutine.
La mia domanda è questa: Esistono oggi linguaggi che fanno distinzioni simboliche tra questi tipi di scenari e impongono vincoli in fase di compilazione su quale codice è effettivamente possibile scrivere?
(Naturalmente c'è un supporto alcuni per questo nella maggior parte dei linguaggi moderni, come i diversi livelli di scopo e chiusura, la separazione tra codice statico e codice di istanza, funzioni lambda, eccetera. questi sembrano entrare in conflitto tra loro: ad esempio, una funzione lambda di solito è puramente funzionale e restituisce semplicemente un valore basato su parametri di input, o muta in qualche modo i parametri di input, ma di solito è possibile accedere a variabili da una funzione lambda, che a sua volta può darti accesso alle variabili di istanza, e quindi tutto si spezza.)