Programmazione funzionale e programmazione non funzionale

Nel mio secondo anno di università ci “insegnavano” Haskell, non ne so quasi nulla e ancor meno sulla programmazione funzionale.

Che cos’è la programmazione funzionale, perché e / xor dove dovrei usarla invece di programmazione non funzionale e ho ragione nel ritenere che C sia un linguaggio di programmazione non funzionale?

Una caratteristica chiave in un linguaggio funzionale è il concetto di funzioni di prima class. L’idea è che puoi passare funzioni come parametri ad altre funzioni e restituirle come valori.

La programmazione funzionale prevede la scrittura di codice che non cambia stato. La ragione principale per farlo è che le chiamate successive a una funzione produrranno lo stesso risultato. Puoi scrivere codice funzionale in qualsiasi linguaggio che supporti le funzioni di prima class, ma ci sono alcune lingue, come Haskell, che non ti permettono di cambiare stato. In effetti, non dovresti fare alcun effetto collaterale (come stampare del testo) – il che sembra che potrebbe essere completamente inutile.

Haskell impiega invece un diverso approccio all’IO: monadi. Questi sono oggetti che contengono l’operazione IO desiderata che deve essere eseguita dal primo livello dell’interprete. Ad ogni altro livello sono semplicemente oggetti nel sistema.

Quali vantaggi offre la programmazione funzionale? La programmazione funzionale consente la codifica con un minor numero di potenziali bug, poiché ogni componente è completamente isolato. Inoltre, l’utilizzo delle funzioni di ricorsione e di prima class consente di ottenere semplici prove di correttezza che in genere rispecchiano la struttura del codice.

Cos’è la programmazione funzionale

Oggi esistono due definizioni diverse di “programmazione funzionale”:

La definizione più vecchia (originata da Lisp) è che la programmazione funzionale riguarda la programmazione usando funzioni di prima class, cioè dove le funzioni sono trattate come qualsiasi altro valore in modo da poter passare funzioni come argomenti ad altre funzioni e la funzione può restituire funzioni tra i loro valori di ritorno. Questo culmina nell’uso di funzioni di ordine superiore come la map e la reduce (potresti aver sentito parlare di mapReduce come una singola operazione usata pesantemente da Google e, non sorprendentemente, si tratta di un parente stretto!). I tipi .NET System.Func e System.Action rendono disponibili le funzioni di ordine superiore in C #. Sebbene il curring non sia pratico in C #, le funzioni che accettano altre funzioni come argomenti sono comuni, ad esempio la funzione Parallel.For .

La definizione più recente (resa popolare da Haskell) è che la programmazione funzionale riguarda anche la minimizzazione e il controllo degli effetti collaterali, compresa la mutazione, ovvero la scrittura di programmi che risolvono problemi mediante la composizione di espressioni. Questo è più comunemente chiamato “programmazione puramente funzionale”. Ciò è reso ansible da approcci estremamente diversi alle strutture dati chiamate “strutture dati puramente funzionali”. Un problema è che la traduzione di algoritmi imperativi tradizionali per utilizzare strutture dati puramente funzionali tipicamente peggiora le prestazioni 10 volte. Haskell è l’unico linguaggio di programmazione puramente funzionale sopravvissuto ma i concetti si sono insinuati nella programmazione mainstream con librerie come Linq su .NET.

dove vorrei usarlo invece di programmazione non funzionale

Ovunque. Lambdas in C # ha ora dimostrato importanti benefici. C ++ 11 ha lambda. Non ci sono scuse per non usare le funzioni di ordine superiore ora. Se è ansible utilizzare una lingua come F # trarrà vantaggio dall’inferenza di tipo, dalla generalizzazione automatica, dal currying e dall’applicazione parziale (oltre a molte altre funzionalità linguistiche!).

ho ragione nel ritenere che C sia un linguaggio di programmazione non funzionale?

Sì. C è un linguaggio procedurale. Tuttavia, è ansible ottenere alcuni dei vantaggi della programmazione funzionale utilizzando i puntatori di funzione e void * in C.

Può valere la pena di esaminare questo articolo su F # “101” su CoDe Mag pubblicato di recente.

Inoltre, Dustin Campbell ha un grande blog in cui ha pubblicato molti articoli sulle sue avventure per diventare subito operativo con F # ..

Spero che tu trovi questi utili 🙂

MODIFICARE:

Inoltre, per aggiungere, la mia comprensione della programmazione funzionale è che tutto è una funzione, o parametri di una funzione, piuttosto che istanze / oggetti stateful. Ma potrei sbagliarmi. F # è qualcosa che muoio dalla voglia di entrare ma semplicemente non avere il tempo! 🙂

Il codice di esempio di John the Statistician non mostra la programmazione funzionale, perché quando si esegue la programmazione funzionale, la chiave è che il codice NON record = thingConstructor(t) è un incarico) e NON localMap.put(record) EFFETTI COLLATERALI ( localMap.put(record) è una dichiarazione con un effetto collaterale). Come risultato di questi due vincoli, tutto ciò che una funzione fa è completamente catturato dai suoi argomenti e dal suo valore di ritorno. Riscrivere il codice dello Statistico come dovrebbe apparire, se si desidera emulare un linguaggio funzionale usando C ++:

 RT getOrCreate (cosa const t, 
                   const Function > thingConstructor, 
                   mappa const > localMap) {
     restituire localMap.contains (t)?
         localMap.get (t):
         localMap.put (t, thingConstructor (t));
 }

Come risultato della regola senza effetti collaterali, ogni istruzione fa parte del valore restituito (quindi il return viene prima ) e ogni istruzione è un’espressione. Nelle lingue che impongono la programmazione funzionale, la parola chiave return è implicita e l’istruzione if si comporta come l’operatore ?: C:?

Inoltre, tutto è immutabile, quindi localMap.put deve creare una nuova copia di localMap e restituirla, invece di modificare la mappa locale originale, come farebbe un normale programma C ++ o Java. A seconda della struttura di localMap, la copia potrebbe riutilizzare i puntatori nell’originale, riducendo la quantità di dati che deve essere copiata.

Alcuni dei vantaggi della programmazione funzionale includono il fatto che i programmi funzionali sono più brevi ed è più facile modificare un programma funzionale (perché non ci sono effetti globali nascosti da tenere in considerazione) ed è più facile ottenere il programma direttamente nel primo posto.

Tuttavia, i programmi funzionali tendono a funzionare lentamente (a causa di tutte le copie che devono fare) e non tendono ad interagire bene con altri programmi, processi del sistema operativo o sistemi operativi, che trattano gli indirizzi di memoria, little-endian blocchi di byte e altri bit non specifici della macchina. Il grado di non interoperabilità tende ad essere inversamente correlato al grado di purezza funzionale e alla severità del sistema di tipo.

I linguaggi funzionali più popolari hanno sistemi di tipo veramente molto rigidi. In OCAML, non puoi nemmeno mischiare numeri interi e matematici in virgola mobile, o usare gli stessi operatori (+ è per aggiungere numeri interi, + è per aggiungere float). Questo può essere un vantaggio o uno svantaggio, a seconda di quanto valuti la capacità di un correttore di tipi di catturare determinati tipi di bug.

Anche i linguaggi funzionali tendono ad avere ambienti di runtime veramente grandi. Haskell è un’eccezione (gli eseguibili di GHC sono quasi piccoli come i programmi C, sia in fase di compilazione che in fase di esecuzione), ma i programmi SML, Common Lisp e Scheme richiedono sempre tonnellate di memoria.

Sì, hai ragione nel pensare che C sia un linguaggio non funzionale. C è un linguaggio procedurale.

Preferisco usare la programmazione funzionale per salvarmi dal lavoro ripetuto, facendo una versione più astratta e poi usando quella. Lasciatemi fare un esempio. In Java, mi trovo spesso a creare mappe per registrare strutture e quindi scrivere strutture getOrCreate.

 SomeKindOfRecord getOrCreate(T thing) { if(localMap.contains(t)) { return localMap.get(t); } SomeKindOfRecord record = new SomeKindOfRecord(t); localMap = localMap.put(t,record); return record; } 

Questo succede molto spesso. Ora, in un linguaggio funzionale potrei scrivere

 RT getOrCreate(T thing, Function> thingConstructor, Map> localMap) { if(localMap.contains(t)) { return localMap.get(t); } RT record = thingConstructor(t); localMap = localMap.put(t,record); return record; } 

e non avrei mai dovuto scriverne uno nuovo, potrei ereditarlo. Ma potrei farne uno migliore ereditando, potrei dire nel costruttore di questa cosa

 getOrCreate = myLib.getOrCreate(*, SomeKindOfRecord.constructor(), localMap); 

(dove * è una sorta di notazione “lascia questo parametro aperto”, che è una sorta di curriculum)

e quindi il getOrCreate locale è esattamente lo stesso di come sarebbe stato se avessi scritto tutto, in una riga, senza dipendenze di ereditarietà.

Se stai cercando un buon testo su F #

Expert F # è co-scritto da Don Syme. Creatore di F #. Ha lavorato su generici in .NET in modo specifico per creare F #.

F # è modellato su OCaml quindi qualsiasi testo OCaml ti aiuterà a imparare anche F #.

Trovo cosa è la programmazione funzionale? per essere utile

La programmazione funzionale riguarda la scrittura di funzioni pure, ovvero la rimozione di input e output nascosti il ​​più lontano ansible, in modo che la maggior parte ansible del nostro codice descriva semplicemente una relazione tra input e output.

Preferisci esplicito when param

 public Program getProgramAt(TVGuide guide, int channel, Date when) { Schedule schedule = guide.getSchedule(channel); Program program = schedule.programAt(when); return program; } 

al di sopra di

 public Program getCurrentProgram(TVGuide guide, int channel) { Schedule schedule = guide.getSchedule(channel); Program current = schedule.programAt(new Date()); return current; } 

Un linguaggio funzionale è triggersmente ostile agli effetti collaterali. Gli effetti collaterali sono la complessità e la complessità sono bug e gli errori sono il diavolo. Un linguaggio funzionale ti aiuterà a essere anche ostile agli effetti collaterali.

Nell’informatica, la programmazione funzionale è un paradigma di programmazione – uno stile di costruzione della struttura e degli elementi dei programmi per computer – che tratta il calcolo come la valutazione delle funzioni matematiche ed evita i dati c pendenti e mutevoli . È un paradigma di programmazione dichiarativa, il che significa che la programmazione è fatta con le espressioni. Nel codice funzionale, il valore di uscita di una funzione dipende solo dagli argomenti che vengono immessi nella funzione, quindi chiamare una funzione f due volte con lo stesso valore per un argomento x produrrà lo stesso risultato f (x) ogni volta . Eliminare gli effetti collaterali, cioè i cambiamenti di stato che non dipendono dagli input delle funzioni, può rendere molto più facile comprendere e prevedere il comportamento di un programma, che è una delle motivazioni chiave per lo sviluppo della programmazione funzionale. vedi per maggiori dettagli in wiki . alcuni esempi di linguaggi di programmazione funzionale sono come scala, javascript, ecc