Se possiamo fare programmazione funzionale con Python, abbiamo bisogno di un linguaggio di programmazione funzionale specifico? [chiuso]

22

Usando generatori e lambda, possiamo fare programmazione funzionale con Python. Puoi anche ottenere la stessa cosa con Ruby.

Quindi la domanda è: perché abbiamo bisogno di linguaggi di programmazione funzionale specifici come Erlang, Haskell e Scheme? C'è qualcosa di diverso da questi specifici linguaggi di programmazione funzionale? Perché non possiamo semplicemente usare Python per la programmazione funzionale?

    
posta Joshua Partogi 03.02.2011 - 00:41
fonte

11 risposte

18

Apprezzo la domanda, perché personalmente sono un grande fan sia per Python che per lo stile di programmazione funzionale. Ho una lunga esperienza in Python e recentemente ho iniziato ad imparare Haskell, quindi ecco alcuni punti basati sulle mie esperienze personali sulle differenze tra questi linguaggi, dal punto di vista funzionale.

Purezza

Anche se non ti interessa la purezza delle funzioni (cioè non avere effetti collaterali) come un principio principe, ha un effetto pratico su quanto sia facile leggere il codice e la ragione su di esso. Anche se mantieni la purezza nelle tue funzioni Python, c'è una grande differenza nel far sì che il compilatore imponga la purezza e, soprattutto, che la libreria standard sia costruita su termini di purezza e strutture di dati immutabili.

Performance

Potresti o meno preoccuparti delle prestazioni a seconda di quale sia il tuo dominio dell'applicazione, ma la tipizzazione statica e la purezza garantita danno al compilatore molto più lavoro rispetto a Python e altri linguaggi dinamici (anche se devo ammettere che PyPy sta facendo grandi incursioni, e ad esempio LuaJIT è al limite del miracoloso).

Ottimizzazione della coda

Correlato alle prestazioni, ma leggermente diverso. Anche se non ti preoccupi troppo delle prestazioni di runtime, non avendo l'ottimizzazione tail-call (specialmente per la ricorsione in coda) limiti i modi in cui puoi implementare algoritmi in Python senza superare i limiti di stack.

Sintassi

Questa è la ragione principale per cui ho iniziato a guardare linguaggi funzionali "reali" invece di usare semplicemente Python con uno stile funzionale. Anche se penso che Python abbia una sintassi molto espressiva in generale, ha alcuni punti deboli specifici per la codifica funzionale. Ad esempio:

  • La sintassi per le funzioni lambda è piuttosto dettagliata e limitata in ciò che può contenere
  • Nessuno zucchero sintattico per la composizione della funzione, ovvero f = g . h vs. f = lambda *arg: g(h(*arg))
  • Nessuno zucchero sintattico per l'applicazione parziale, ovvero f = map g rispetto a f = functools.partial(map, g)
  • Nessuno zucchero sintattico per l'utilizzo degli operatori infissi nelle funzioni di ordine superiore, ovvero sum = reduce (+) lst rispetto a sum = reduce(operator.add, lst)
  • Nessuna corrispondenza di pattern o guardie per gli argomenti delle funzioni, che rendono facile esprimere le condizioni di fine ricorsione e alcuni casi di confine con una sintassi molto leggibile.
  • Le parentesi non sono mai opzionali per le chiamate di funzione e non c'è zucchero sintattico per le chiamate nidificate. Immagino che sia una questione di gusti, ma soprattutto nel codice funzionale, trovo che sia comune raggruppare le chiamate di funzione e trovo che y = func1 $ func2 $ func3 x è più facile da leggere di y = func1(func2(func3(x))) , una volta che hai familiarità con quella notazione.
risposta data 09.02.2011 - 08:37
fonte
28

Queste sono le differenze più importanti:

Haskell

  • Valutazione pigra
  • Compila il codice macchina
  • La tipizzazione statica garantisce che le funzioni siano pure
  • Tipo di inferenza

Haskell e Erlang

  • Corrispondenza dei pattern

Erlang

  • Modello attore di concorrenza, processi leggeri

Schema

  • Macro

Tutte le lingue

  • chiusure reali (ruby ha chiusure, se il pitone può essere discusso, vedere i commenti)
  • una libreria standard adatta per uno stile di programmazione funzionale (collezioni, mappe, filtri, pieghe ecc.)
  • ricorsione a coda (questa può essere trovata anche in alcune lingue non funzionali)

Inoltre, dovresti dare un'occhiata alle lingue della famiglia ML come SML, Ocaml e F # e Scala, che fondono OO e la programmazione funzionale in un modo nuovo. Tutte queste lingue hanno caratteristiche interessanti uniche.

    
risposta data 03.02.2011 - 04:29
fonte
19

È difficile definire esattamente che cosa sia un "linguaggio funzionale": fuori dalle lingue che hai elencato, solo Haskell è puramente funzionale (tutti gli altri adottano una sorta di approccio ibrido). Ci sono alcune caratteristiche del linguaggio che sono molto utili per la programmazione funzionale, però, e Ruby e Python non ne hanno abbastanza per essere ambienti molto buoni per FP. Ecco la mia lista di controllo personale, in ordine di importanza:

  1. Funzioni di prima classe e chiusure (Ruby, Python e tutti gli altri che hai elencato hanno questo).
  2. Garantito ottimizzazione della chiamata di coda (Erlang, Haskell, Scala e Scheme hanno questo, ma non Python, Ruby, o Clojure (ancora)).
  3. Supporto per immutabilità nella lingua e nelle librerie standard (questo è un grande che tutti i "linguaggi funzionali" hai elencato (tranne Scheme) ma Ruby e Python no).
  4. Supporto a livello di lingua per le funzioni (o pure) (per quanto ne so, solo Haskell ha questo al momento).

La necessità di (1) dovrebbe essere ovvia - le funzioni di ordine superiore sono estremamente difficili senza funzioni di prima classe. Quando le persone parlano di Ruby e Python che sono buone lingue per FP, di solito parlano di questo. Tuttavia, questa particolare caratteristica è necessaria ma non sufficiente per rendere un linguaggio valido per FP.

(2) è stata una necessità tradizionale per FP fin da quando Scheme è stato inventato. Senza TCO, è impossibile programmare con ricorsione profonda, che è uno dei capisaldi di FP, perché si ottengono overflow dello stack. L'unico linguaggio "funzionale" (per definizione popolare) che non ha questo è Clojure (a causa delle limitazioni della JVM), ma Clojure ha una varietà di hack per simulare il TCO. (FYI, Il TCO di Ruby è specifico per l'implementazione , ma Python specificamente non lo supporta .) La ragione per cui il TCO deve essere garantito è che, se le funzioni ricorsive profonde specifiche dell'implementazione si interromperanno con alcune implementazioni, quindi non puoi davvero usarle affatto.

(3) è un'altra cosa importante che i linguaggi funzionali moderni (specialmente Haskell, Erlang, Clojure e Scala) hanno che Ruby e Python non lo fanno. Senza entrare troppo nel dettaglio, l'immutabilità garantita elimina intere classi di bug, soprattutto in situazioni concorrenti, e consente di ordinare cose carine come strutture dati persistenti . È molto difficile sfruttare questi vantaggi senza il supporto a livello di lingua.

(4) è, per me, la cosa più interessante dei linguaggi puramente funzionali (al contrario dei linguaggi ibridi). Considera la seguente estremamente semplice funzione Ruby:

def add(a, b)
  a + b
end

Sembra una pura funzione, ma a causa dell'overloading dell'operatore, potrebbe mutare i parametri o causare effetti collaterali come la stampa sulla console. È improbabile che qualcuno sovraccarichi l'operatore + per avere un effetto collaterale, ma il linguaggio non fornisce garanzie. (Lo stesso vale per Python, anche se forse non con questo specifico esempio.)

In un linguaggio puramente funzionale, d'altra parte, ci sono garanzie a livello linguistico che le funzioni sono referenzialmente trasparenti. Questo ha numerosi vantaggi: le funzioni pure possono essere facilmente memorizzate; possono essere facilmente testati senza fare affidamento su alcun tipo di stato globale; e i valori all'interno della funzione possono essere valutati pigramente o in parallelo senza preoccuparsi di problemi di concorrenza. Haskell ne approfitta pienamente, ma non ne so abbastanza di altri linguaggi funzionali per sapere se lo fanno.

Tutto ciò detto, è possibile utilizzare le tecniche FP in quasi tutti i linguaggi (anche Java). Ad esempio, il MapReduce di Google è ispirato a idee funzionali, ma per quanto ne so non usano alcun "funzionale" lingue per i loro grandi progetti (penso che utilizzino principalmente C ++, Java e Python).

    
risposta data 03.02.2011 - 06:32
fonte
11

Le lingue che menzioni sono molto diverse.

Mentre Python e Ruby sono lingue tipizzate dinamicamente, Haskell è tipizzato staticamente. Erlang è un linguaggio concorrente e utilizza il modello di attore ed è molto diverso da tutte le altre lingue menzionate.

Python e Ruby hanno molti costrutti imperativi mentre in un linguaggio funzionale più puro come Haskell, tutto restituisce qualcosa o in altre parole tutto è una funzione.

    
risposta data 03.02.2011 - 00:47
fonte
7

In ritardo alla festa come al solito, ma andando a dire le cose comunque.

Un linguaggio di programmazione funzionale non è un linguaggio che consente di programmazione funzionale. Se dovessimo seguire quella definizione, praticamente qualsiasi lingua in qualsiasi luogo è un linguaggio di programmazione funzionale. (Lo stesso vale per OOP, tra l'altro. Puoi scrivere in uno stile OOP in C se vuoi. Quindi, secondo la tua logica, C è un linguaggio OOP.)

Ciò che rende un linguaggio di programmazione funzionale non è ciò che consente di programmare come, è ciò che ti permette di programmare come facilmente . Questa è la chiave.

Quindi, Python ha lambda (che sono affari di chiusura incredibilmente anemici) e ti offre un paio di funzioni di libreria che vedrai anche nelle librerie funzionali come "mappa" e "piega". Questo non è sufficiente per renderlo un linguaggio di programmazione funzionale, tuttavia, poiché è difficile da programmare in modo coerente in uno stile funzionale appropriato in esso (e la lingua certamente non lo fa 'applica questo stile!). Al suo interno Python è un linguaggio imperativo interessato alle operazioni di manipolazione di stato e stato e questo è semplicemente in contrasto con la semantica di espressione ed espressione di un linguaggio funzionale.

Quindi perché abbiamo linguaggi di programmazione funzionali quando Python (o Ruby (o inserisci la lingua di tua scelta)) può "fare programmazione funzionale"? Perché Python, et al non può fare la corretta programmazione funzionale. Ecco perché.

    
risposta data 09.02.2011 - 13:25
fonte
6

Tu puoi fare programmazione funzionale in Java (vedi per esempio link ). Puoi anche fare programmazione orientata agli oggetti in C . Non è solo idiomatico.

Quindi in effetti non abbiamo assolutamente bisogno di Erlang, Haskell, Scheme o qualsiasi linguaggio di programmazione specifico, ma rappresentano tutti diversi approcci e diversi compromessi, rendendo alcuni compiti più facili e alcuni più difficili. Quello che dovresti usare dipende da ciò che vuoi ottenere.

    
risposta data 03.02.2011 - 11:08
fonte
4

Questa domanda può essere applicata a un numero infinito di lingue e paradigmi.

  • Dal momento che tutti usano C ++, perché abbiamo bisogno di altre lingue generiche?
  • Poiché java è un linguaggio OO così grande, perché esistono altri linguaggi OO?
  • Poiché perl è un linguaggio di scripting sorprendente, perché abbiamo bisogno di python?
  • Yatta, yatta, yatta

La maggior parte, se non tutte le lingue esistono per una ragione specifica. Esistono perché qualcuno aveva bisogno che nessuna lingua corrente fosse riempita o riempita male. (Questo ovviamente non si applica a tutte le lingue, ma ritengo che si applichi alla maggior parte dei linguaggi conosciuti.) Ad esempio, python è stato originariamente sviluppato per interfacciarsi con il sistema operativo Amoeba [ 1 , 2 ] ed Erlang è stato creato per aiutare nello sviluppo di applicazioni di telefonia [ 3 ]. Quindi una risposta alla domanda "Perché abbiamo bisogno di un altro linguaggio funzionale?" può semplicemente essere, perché [inserire-nome-di-qualcuno-chi-sa-come-design-lingue]] non ha gradito il modo in cui Python lo ha fatto.

Questo riassume in sostanza ciò che penso sia la risposta. Mentre puoi fare qualsiasi cosa con Python che puoi fare con un linguaggio funzionale, vorresti davvero? Tutto quello che puoi fare in C, puoi farlo in assemblea, ma vorresti? Lingue diverse saranno sempre le migliori a fare cose diverse, e così dovrebbe essere.

    
risposta data 03.02.2011 - 18:50
fonte
2

La programmazione funzionale riguarda tanto il paradigma del design quanto le caratteristiche linguistiche specifiche. In altre parole, lambda e una funzione mappa non fanno un linguaggio di programmazione funzionale. Python e Ruby hanno alcune caratteristiche ispirate ai linguaggi di programmazione funzionale, ma in genere si scrive codice in modo molto imperativo. (È un po 'come C: puoi scrivere codice simile a OO in C, ma nessuno considera seriamente che C sia un linguaggio OO.)

Guarda: la programmazione funzionale non riguarda solo lambdas, o map , o funzioni di ordine superiore. Riguarda design . Un programma scritto in un linguaggio di programmazione funzionale "vero" risolve i problemi tramite la composizione delle funzioni. Mentre i programmi scritti in Ruby o Python possono utilizzare funzionalità simili a FP, in genere non vengono letti come un insieme di funzioni composte.

    
risposta data 03.02.2011 - 18:16
fonte
0

Ogni linguaggio funzionale che hai citato si inserisce in una certa nicchia abbastanza bene e gli schemi idiomatici che ognuno incoraggia li rende molto adatti per determinati compiti che sarebbero impossibili da realizzare in Python a meno che tu non abbia costruito un'enorme libreria di moduli helper. La più ovvia di una di queste eccellenze di nicchia è il modello di concorrenza di Erlang. Anche gli altri hanno punti di forza simili.

    
risposta data 03.02.2011 - 06:37
fonte
0

Ogni concetto disponibile in lambda-calculus, LISP e Scheme è disponibile in Python, quindi, sì, puoi fare programmazione funzionale in esso. Se è conveniente o no è una questione di contesto e gusto.

Puoi facilmente scrivere un interprete LISP (o altro linguaggio funzionale) in Python (Ruby, Scala) (cosa significa?). Puoi scrivere un interprete per Python usando puramente funzionale, ma ci vorrebbe molto lavoro. Al giorno d'oggi, anche le lingue "funzionali" sono multi-paradigma.

Questo vecchio e bellissimo libro ha la maggior parte (anche se non tutte) le risposte su quale sia l'essenza della programmazione funzionale.

    
risposta data 03.02.2011 - 08:48
fonte
-5

Perché Python può anche programmare in uno stile non funzionale, e questo non è abbastanza buono per il purificatore FP. I programmatori più pragmatici, tuttavia, possono godere dei benefici dello stile funzionale senza essere dogmatici al riguardo:

“The functional programmer sounds rather like a medieval monk, denying himself the pleasures of life in the hope that it will make him virtuous. To those more interested in material benefits, these “advantages” are not very convincing. Functional programmers argue that there are great material benefits … [but] this is plainly ridiculous. If omitting assignment statements brought such enormous benefits then FORTRAN programmers would have been doing it for twenty years. It is a logical impossibility to make a language more powerful by omitting features, no matter how bad they may be.”

- John Hughes, Perché la programmazione funzionale conta

    
risposta data 03.02.2011 - 00:49
fonte