Come risultato della discussione di commento qui , mi chiedo se puoi imparare la programmazione funzionale in C?
Come risultato della discussione di commento qui , mi chiedo se puoi imparare la programmazione funzionale in C?
Risposte:
Ovviamente puoi fare la programmazione funzionale in C. In teoria, puoi anche imparare i principi di programmazione funzionale in C, ma il linguaggio non lo rende facile.
Presumo che tu abbia almeno un po 'di background in OOP; se lo fai, dovresti essere consapevole che OOP può essere fatto in C, incluso polimorfismo, getter / setter, regole di visibilità, ecc. ecc., ma è abbastanza doloroso farlo, e devi conoscere sia OOP che C all'interno- fuori per farlo fuori. È quasi lo stesso con FP.
Quello che dovresti fare è prima imparare un linguaggio di programmazione funzionale (la maggior parte di loro ha regole di sintassi sorprendentemente semplici; non è la sintassi che li rende difficili da imparare), quindi lascia che la tua saggezza appena acquisita influenzi il modo in cui scrivi C.
Come da richiesta, alcune cose che puoi imparare da FP e quindi applicare in, diciamo, C, C ++ o Java:
C può essere hackerato per offrire alcuni concetti funzionali:
Questa domanda StackOverflow ti dirà di più. Ma anche se sembra possibile fare una programmazione funzionale (o un ampio sottoinsieme di) in C, hack ed estensioni del compilatore e qualunque cosa non sia il modo migliore per imparare un concetto.
Per imparare davvero la programmazione funzionale, la soluzione migliore è uno dei principali linguaggi di programmazione funzionale come Lisp e i suoi dialetti ( Clojure , Scheme ), Erlang e Haskell . Ognuno di questi sono strumenti perfetti che funzionano all'interno della mentalità di programmazione funzionale. F # è anche un buon candidato se hai un background .Net, ma è un linguaggio multi paradigma, non strettamente un linguaggio di programmazione funzionale.
Come osserva tdammers nei commenti:
In realtà, LISP, clojure e schema sono anche multi-paradigma; Haskell, pur essendo puro e predefinito-pigro, consente anche una programmazione imperativa in un contesto monadico e ha un ampio supporto per l'elaborazione simultanea. Tutti questi hanno meccanismi che implementano gran parte della saggezza raccolta nel mondo OOP - incapsulamento, eredità, responsabilità individuale, composizione, ecc. riguarda quale paradigma costituisce il punto di partenza di una lingua.
Per quanto ne so , Lisp, i suoi dialetti ed Erlang sono candidati migliori di F # perché incoraggiano la programmazione funzionale su altri paradigmi, ciò che tdammer afferma magnificamente come punto di partenza di una lingua . F # comprende la programmazione funzionale ma non la incoraggia rispetto agli altri paradigmi supportati, la programmazione imperativa e oo.
Non puoi imparare tutti gli aspetti della programmazione funzionale in C. Ma sicuramente puoi iniziare la programmazione dello stile funzionale con qualsiasi linguaggio imperativo. Questi bit di partenza sono: "Come mantenere le cose pure durante la programmazione." E si può fare anche C. Controlla questo post del blog per i dettagli-
http://www.johndcook.com/blog/2011/07/24/get-started-functional-programming/
La programmazione funzionale riguarda le chiusure e le loro applicazioni. A meno che qualcuno non sia in grado di mostrarti una libreria di chiusura di discesa per C, dimentica di usare C per imparare la programmazione funzionale.
Il concetto cardine della programmazione funzionale è la nozione di chiusure che, in termini approssimativi, catturano una funzione insieme a associazioni di variabili. Oltre all'uso pervasivo delle chiusure, ci sono alcuni altri tratti distintivi nella programmazione funzionale, come l'uso di funzioni ricorsive e valori immutabili (entrambi giocano bene insieme). Questi tratti sono più un problema culturale che altro, e non esiste alcun ostacolo tecnico per usarli praticamente in qualsiasi lingua, per questo mi concentro sulle chiusure nella mia risposta: non tutte le lingue consentono di creare facilmente chiusure.
Un uso tipico delle chiusure è l'implementazione di meccanismi di privacy. Ad esempio il codice Javascript - negli esempi ho scelto Javascript perché è un linguaggio funzionale con una cosiddetta "sintassi simil-C" e la tua domanda suggerisce che hai familiarità con C:
create_counter = function()
{
var x = 0;
var counter = function()
{
++x;
return x;
};
return counter;
}
Quindi con
a = create_counter();
b = create_counter();
abbiamo due funzioni a
e contiamo b
raccolte disgiunte. Il punto dell'esempio è che le variabili x
vengono catturate dalla chiusura che definisce la counter
chiusura e ogni volta che una nuova counter
chiusura is instantiated by the function, it gets its fresh own idea of what
è x`.
Un altro uso tipico delle chiusure è la definizione di applicazioni parziali di funzioni. Supponiamo che abbiamo una struttura di reporting simile syslog
all'implementazione di una funzione
var log = function(priority, message) {
…
};
dove gli argomenti priority
e message
si pensano che siano stringhe, il primo è uno dei "debug"
, "info"
e così via. Possiamo definire una fabbrica di tronchi come questa:
var logWithPriority = function(priority) {
return function(message) {
log(priority, message);
};
};
e utilizzarlo per definire versioni specializzate della nostra funzione di registro:
var debug = logWithPriority("debug");
var info = logWithPriority("info");
…
Questo è molto utile, perché invece di scrivere in for
questo modo soggetti a errori
for(i = 0; i < journal.length; ++i) {
log("info", journal[i]);
}
possiamo scrivere in modo più pulito, più breve e molto più semplice (non c'è i
, è molto meglio):
journal.forEach(logWithPriority("info"));
Un terzo importante campo di applicazione delle chiusure è l'implementazione della valutazione pigra - si noti che il supporto linguistico speciale può fornire una migliore implementazione.
Una funzione pigra, invece di eseguire un calcolo diretto, restituisce una chiusura che può essere chiamata (o "forzata" nel gergo della pigrizia) per eseguire la domanda. La motivazione per fare ciò è che separa la preparazione di un calcolo e l'esecuzione di un calcolo. Un esempio pratico di ciò è la compilazione di espressioni regolari: se un programma compila molte espressioni regolari al momento dell'avvio, avrà bisogno di molto tempo per avviarsi. Se invece compiliamo pigramente le espressioni regolari e le forziamo quando ne abbiamo bisogno, allora il nostro programma può iniziare rapidamente. Naturalmente, le espressioni regolari possono essere sostituite qui con qualsiasi struttura che richieda un considerevole tempo di inizializzazione.
Ecco come implementare la valutazione pigra con le chiusure. Considera l'implementazione classica della funzione arrayMax che restituisce il massimo in un array:
function arrayMax(array) {
return array.reduce(function(a, b) {
return Math.min(a, b);
};
}
La variante pigra sarebbe:
function arrayMax(array) {
var memo = null;
function actuallyCompute() {
if(memo === null) {
memo = array.reduce(function(a, b) {
return Math.min(a, b);
});
}
return memo;
}
return actuallyCompute;
}
Il valore restituito è una chiusura che può essere utilizzata per calcolare il valore o recuperarlo un'altra volta se è già stato calcolato.
Con questi tre esempi, dovremmo essere certi che le chiusure e le loro applicazioni sono il nucleo della programmazione funzionale.
Imparare la programmazione funzionale significa imparare a programmare con le chiusure. Di conseguenza, le lingue che consentono la facile manipolazione delle chiusure, e in particolare l'applicazione parziale delle funzioni, dovrebbero essere considerate quando si cerca una lingua per studiare la programmazione funzionale. Al contrario, le lingue in cui le chiusure non possono essere facilmente manipolate sarebbero scelte sbagliate.
Penso che gli strumenti che usi influenzino molto il tuo apprendimento. È quasi impossibile imparare concetti di programmazione per i quali il linguaggio di programmazione che usi non fornisce i mezzi per farne uso. Certo, puoi sempre imparare alcune cose, ma non puoi impararlo correttamente.
Ma questo è comunque accademico, perché, come afferma Martinho nel suo commento , anche se potessi imparare la programmazione funzionale, non dovresti provare a farlo, perché ci sono lingue in cui questo è molto più semplice.
Non dovresti imparare la programmazione funzionale in C, ma in un linguaggio funzionale rigoroso (Haskell, Caml, Erlang, ecc.).
Se sei nuovo al funzionale, non lo otterrai mai con un linguaggio non funzionale. Più probabilmente, ti allenerai per fare ciò che pensi sia una programmazione funzionale e apprendere le cose nel modo sbagliato. Ed è sempre più difficile «riapprendere» le cose nel modo giusto piuttosto che impararle nel modo giusto all'inizio.
Comunque, penso che fare funzionale in C sia un buon esercizio per qualcuno che già conosce funzionale. Perché quella persona imparerà cosa sta succedendo dietro il cofano - cosa sta realmente facendo il computer.