Lingue con una chiara distinzione tra subroutine che sono puramente funzionali, mutevoli, modificabili, ecc.?

8

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.)

    
posta Christian Palmstierna 22.06.2012 - 12:59
fonte

3 risposte

10

Sì, vuoi dare un'occhiata a Haskell. Fa esattamente quello che vuoi. Tutte le funzioni sono pure di default e possono solo cambiare stato usando Monade. Inoltre Haskell ha garanzie statiche molto forti su tutti i tipi di cose link

    
risposta data 22.06.2012 - 13:01
fonte
6

C e C ++ hanno un supporto molto limitato per almeno parte del problema attraverso la parola chiave const ; mentre questo da solo non controlla la purezza, può essere usato (specialmente in C ++) per dire al compilatore che una particolare struttura di dati non deve essere modificata attraverso un dato puntatore. Alcuni compilatori (ad esempio gcc) forniscono anche un attributo "puro" come estensione del linguaggio per applicare completamente la purezza. (Vedi questa domanda per i dettagli).

Il linguaggio di programmazione D supporta la dichiarazione della purezza delle funzioni in modo esplicito e i compilatori controllano e impongono la purezza (ovvero, provare a chiamare una funzione non pura all'interno di una funzione pura produce un errore del compilatore).

Haskell è completamente puro, cioè il linguaggio stesso non può esprimere funzioni impure e non esiste un concetto di "routine". Tutto ciò che non può essere risolto utilizzando solo le funzioni pure viene esternalizzato al runtime (impuro); un programma con effetti collaterali è implementato costruendo (usando esclusivamente costrutti puri) una struttura di dati lazy che descrive il comportamento del programma e quindi passandolo al runtime. La comunità Haskell sta sperimentando attivamente con un intero zoo di linguaggi di programmazione, alcuni dei quali puri, altri con purezza esplicita.

Potrebbero essercene di più, ma questi sono quelli con cui ho familiarità.

    
risposta data 22.06.2012 - 13:19
fonte
1

Felix ha tre categorie a quanto pare:

  1. funzioni

    There is a rule for functions: 
    
    A function introduced by a fun binder is not allowed to have any side effects.
    
    The compiler does not enforce this rule, but it does take advantage of it when
    optimising your code. 
    
  2. procedure

    Procedures do not return a value, and may and generally should have side-effects.
    
  3. generatori

    A generator is a function that may have side effects.
    
risposta data 22.06.2012 - 17:00
fonte

Leggi altre domande sui tag