Gli interpreti non puri offrono ancora le garanzie della programmazione funzionale?

5

Sto assumendo che le implementazioni / compilatori / codice C generato (di seguito "generico", "interprete") per la maggior parte dei linguaggi di programmazione funzionale siano scritti in linguaggi funzionali non puri.

Se questo è il caso, l'interprete sottostante per ogni dato linguaggio di programmazione funzionale esibisce aggiornamenti distruttivi ed è referenzialmente opaco. I costrutti funzionali sono progettati per garantire determinate garanzie, come la concorrenza e la provabilità.

Se l'interprete è davvero un programma imperativo, in che modo è in grado di garantire le proprietà "senza effetti collaterali" dei programmi puramente funzionali? Sicuramente le ottimizzazioni del codice funzionale da parte dell'interprete includono la modifica della natura delle funzioni ricorsive a quelle imperative? La mia domanda è:

In che modo gli interpreti imperativi continuano a fornire garanzie sul programma funzionale che stanno eseguendo senza essere intrinsecamente funzionali da soli?

    
posta Daniel Levin 18.04.2012 - 21:38
fonte

6 risposte

10

Tutto nella tua macchina funziona su una CPU che carica e memorizza le parole di memoria, ed esegue comparazioni e rami goto-like.

La programmazione funzionale significa che la mutazione è nascosta sotto il tappeto, non che va via.

Non è fattibile, con la tecnologia attuale, che un linguaggio funzionale possa essere implementato completamente fino in fondo. Questo perché non è possibile continuare a allocare nuovo hardware. I programmi funzionali generano spazzatura mentre vengono eseguiti e l'implementazione deve identificare la spazzatura e quindi riutilizzare la sua memoria per i nuovi oggetti. Questa è una forma di mutazione.

Se questa mutazione non viene eseguita, significa che non riutilizzerai la memoria in serie.

Se non riutilizzi la memoria, devi continuare a ricevere nuova memoria da qualche parte.

Inoltre, non ti è permesso riavviare il computer. Devi usarne uno nuovo.

La CPU deve continuare a allocare nuovi registri, perché non è possibile caricare un nuovo valore in un registro esistente. Et cetera.

Come puoi vedere, la programmazione funzionale è un sogno sciocco che è reso possibile solo dal pragmatismo della mutazione.

Esiste una mutazione intrinseca nella stessa programmazione funzionale (nell'astrazione). È semplicemente ignorato.

Il fatto è che quando costruisci un nuovo oggetto, il mondo è cambiato: non c'era nessun oggetto del genere prima, e ora c'è. La stessa cosa quando entra in gioco una nuova legatura di variabili.

Puoi fingere che sia stato allocato un intero nuovo universo che è proprio come il vecchio, tranne che per la differenza che ora esiste un nuovo elemento, ma non è la realtà. (Se il vecchio "mondo" non è stato mutato / distrutto dalla creazione di un nuovo oggetto, mostrami dov'è quello vecchio.)

Inoltre, nei programmi funzionali, l'oggetto viene distrutto tutto il tempo! I collegamenti variabili (che non vengono catturati in alcune chiusure) escono dall'ambito e gli oggetti cadono dal grafico di raggiungibilità (se non c'è alcuna mutazione, come può qualcosa essere in un grafico in un momento e non essere in quel grafico il prossimo momento?)

Sai che la vecchia copia del mondo non viene preservata, perché quegli oggetti irraggiungibili vengono calpestati per crearne di nuovi.

In altre parole, la distruttività della programmazione funzionale si rivela dall'incapacità di rivisitare tutti gli stati passati di computazione e ispezionare ogni oggetto che sia mai stato creato.

    
risposta data 18.04.2012 - 21:52
fonte
9

A titolo di esempio, passiamo attraverso un banale esempio di un linguaggio di computer chiamato "ALL-CAPS". Questa lingua ha la peculiare qualità (e la regola della lingua) di essere scrivibile solo in tutte le lettere maiuscole.

Posso scrivere il mio compilatore o interprete in una lingua come C #? Certo che posso. C # usa lettere minuscole? Certo che lo fa. Posso ancora richiedere che il mio input di origine sia interamente in maiuscolo? Assolutamente.

Qualcuno con migliori capacità logiche deduttive di quanto io possa logicamente dimostrare che richiedere tutte le protezioni nel codice sorgente del programma è moralmente equivalente a richiedere costrutti puramente funzionali nel codice sorgente.

    
risposta data 18.04.2012 - 21:51
fonte
3

"Programmazione funzionale" è un'astrazione, proprio come "Programmazione orientata agli oggetti". Il tuo "interprete" non deve usare oggetti per implementare oggetti. Allo stesso modo, non è necessario utilizzare le funzioni pure per implementare funzioni pure.

    
risposta data 19.04.2012 - 01:59
fonte
2

Poiché questo è stato etichettato come Scala , vorrei aggiungere che Scala è scritto in gran parte in Scala stessa, con pochissimo in Java. Poi di nuovo, usa alcune librerie scritte in Java, e funziona (principalmente) su una JVM che è scritta principalmente in C / C ++.

    
risposta data 18.04.2012 - 22:53
fonte
2

Ora, tramite la magia di Internet, dimostrerò un puro programma funzionale privo di effetti collaterali, scritto in C, un linguaggio di programmazione decisamente impuro:

int main()
{
    return 0;
}

I programmi C non creano effetti collaterali a meno che tu non glielo dica. Pertanto, la creazione di codice C senza effetti collaterali è relativamente semplice: non inserirli!

    
risposta data 18.04.2012 - 23:45
fonte
0

Beh, non è una contraddizione. Puoi costruire qualsiasi cosa tu voglia in entrambi i paradigmi. La garanzia si ottiene testando e dimostrando, e sicuramente, ci sono bug di implementazione in ogni avvio.

La cosa interessante che mi è venuta in mente mentre leggevo la tua domanda era che quasi tutte le lingue sono alimentate da C, lisp, scheme, python ...

    
risposta data 18.04.2012 - 21:53
fonte

Leggi altre domande sui tag