Ruby è un linguaggio funzionale?


88

Wikipedia dice che Ruby è un linguaggio funzionale, ma non sono convinto. Perché o perché no?


4
Probabilmente perché la tua domanda è molto breve, anche se personalmente non ho alcun problema con essa!
ljs

Ci sono già buone risposte, quindi solo per completarle, un paio di contenuti che parlano di FP e Ruby: code.google.com/p/tokland/wiki/RubyFunctionalProgramming slideshare.net/tokland/functional-programming-with-ruby-9975242
Tokland

1
Se qualcuno è interessato a questo argomento, guarda questo e imparerai come ruby ​​può essere utilizzato in modo funzionale, quali sono le radici della programmazione funzionale, perché ruby ​​non è un linguaggio funzionale anche se è in grado di programmare funzionale: youtube .com / watch? v = 5ZjwEPupybw
maddin2code

Risposte:


29

Sicuramente penso che puoi usare lo stile funzionale in Ruby.

Uno degli aspetti più critici per poter programmare in uno stile funzionale è se il linguaggio supporta funzioni di ordine superiore ... cosa che fa Ruby.

Detto questo, è facile programmare in Ruby anche in uno stile non funzionale. Un altro aspetto chiave dello stile funzionale è non avere uno stato e avere funzioni matematiche reali che restituiscono sempre lo stesso valore per un dato insieme di input. Questo può essere fatto in Ruby, ma non è applicato nel linguaggio come qualcosa di più strettamente funzionale come Haskell.

Quindi, sì, supporta lo stile funzionale, ma ti permetterà anche di programmare in uno stile non funzionale.


4
Usando questo criterio, diresti che Smalltalk è funzionale perché ha dei blocchi?
OscarRyz

Buona risposta ma un problema: le funzioni di ordine superiore non sono strettamente necessarie per uno stile funzionale. Ad esempio, è possibile ottenere uno stile funzionale in Java (che non dispone di funzioni di prima classe / di ordine superiore) definendo oggetti funzione e componendoli per ottenere lo stesso effetto di una funzione di ordine superiore.
mikera

2
Voglio solo affermare che @peter ha chiesto Is ruby a functional language?e in una risposta diretta è un semplice no. Ruby è un linguaggio orientato agli oggetti con alcune caratteristiche funzionali.
Elias Perez

58

Che una lingua sia o meno una lingua funzionale non è importante. La programmazione funzionale è una tesi, meglio spiegata da Philip Wadler (The Essence of Functional Programming) e John Hughes (Why Functional Programming Matters).

Una domanda significativa è: "Quanto è disponibile Ruby a raggiungere la tesi della programmazione funzionale?" La risposta è "molto male".

Ho tenuto un discorso su questo proprio di recente. Ecco le diapositive.


3
Le diapositive che hai fornito non hanno menzionato il motivo per cui Ruby è "molto poco propenso a raggiungere la tesi di FP". Perché C # è più suscettibile di Java (OK, funzioni anonime più semplici?)? È perché puoi avere variabili globali in Ruby?
kizzx2

7
No, le diapositive non entrano in questo dettaglio, poiché questo è un argomento piuttosto ampio. A rischio di un'eccessiva semplificazione, ad esempio, Ruby applica un modello di valutazione (call-by-value) che garantisce la non composizionalità dei programmi. Le implicazioni di ciò possono essere facilmente sottovalutate. Ruby è anche sposata con l'idea che un programma sia una sequenza di effetti. Vale a dire, Ruby fa di tutto per rendere difficile / intrattabile l'utilizzo di qualsiasi altro modello di calcolo. Spero che questo breve commento aiuti.
Tony Morris,

2
+1 per evidenziare l'ambiguità nel classificare le lingue come funzionali. Diavolo, ho scritto C funzionale!
Eli

1
Perché C # è più disponibile di Ruby?
dan_l

1
Effettivamente una risposta solo link in quanto affida la parte critica della spiegazione (l'intera spiegazione, appunto) a un link esterno. Ora che il collegamento è morto, la risposta è diventata inutile.
ivan_pozdeev

34

Ruby supporta funzioni di livello superiore (vedi Array # map, inject, & select), ma è ancora un linguaggio imperativo e orientato agli oggetti.

Una delle caratteristiche chiave di un linguaggio funzionale è che evita lo stato mutevole. I linguaggi funzionali non hanno il concetto di variabile come avresti in Ruby, C, Java o qualsiasi altro linguaggio imperativo.

Un'altra caratteristica chiave di un linguaggio funzionale è che si concentra sulla definizione di un programma in termini di "cosa", piuttosto che "come". Quando programmiamo in un linguaggio OO, scriviamo classi e metodi per nascondere l'implementazione (il "come") dal "cosa" (il nome della classe / metodo), ma alla fine questi metodi vengono comunque scritti utilizzando una sequenza di istruzioni. In un linguaggio funzionale, non specifichi una sequenza di esecuzione, anche al livello più basso.


3
Sono d'accordo con la maggior parte delle tue affermazioni, tuttavia, non sono d'accordo su "I linguaggi funzionali non hanno il concetto di variabili come avresti in Java ecc." In haskell, puoi utilizzare variabili in funzioni pure, puoi persino assegnare una funzione a una variabile, la differenza più grande è che una volta assegnata una variabile non può essere modificata in seguito.
HHC

6
HHC, per definizione, una variabile è un valore che può cambiare . Quello di cui parli sono valori.
Scala Newb

In effetti le "variabili immodificabili" di Haskell sono solo funzioni costanti senza parametri (definizioni).
raindev

16

Affermo che supportare, o avere la capacità di programmare in un linguaggio in uno stile funzionale , non fa un linguaggio funzionale.

Posso persino scrivere codice Java in uno stile funzionale se voglio danneggiare i miei colleghi e me stesso dopo qualche mese, settimane.

Avere un linguaggio funzionale non riguarda solo ciò che puoi fare, come funzioni di ordine superiore, funzioni di prima classe e curry. Riguarda anche ciò che non puoi fare, come gli effetti collaterali nelle funzioni pure.

Questo è importante perché è una parte importante del motivo per cui i programmi funzionali sono, o il codice funzionale in generale è più facile da ragionare. E quando è più facile ragionare sul codice, i bug diventano meno profondi e galleggiano sulla superficie concettuale dove possono essere corretti, il che a sua volta fornisce un codice meno difettoso.

Ruby è essenzialmente orientato agli oggetti, quindi anche se ha un supporto ragionevolmente buono per uno stile funzionale, non è esso stesso un linguaggio funzionale.

Questa è comunque la mia opinione non scientifica.

Modifica: in retrospettiva e tenendo conto dei bei commenti che ho ricevuto finora a questa risposta, penso che il confronto orientato agli oggetti rispetto a quello funzionale sia quello delle mele e delle arance.

Il vero elemento di differenziazione è quello di essere imparziale nell'esecuzione o meno. I linguaggi funzionali hanno l'espressione come loro costrutto linguistico primario e l'ordine di esecuzione è spesso indefinito o definito come pigro. È possibile un'esecuzione rigorosa ma utilizzata solo quando necessario. In un linguaggio imparativo, l'esecuzione rigorosa è l'impostazione predefinita e sebbene sia possibile l'esecuzione lenta, spesso è difficile da fare e può avere risultati imprevedibili in molti casi limite.

Questa è la mia opinione non scientifica.


Penso che tu possa fare un caso molto migliore per chiamare Ruby funzionale rispetto a Java .... no, Ruby non è strettamente funzionale, ma è abbastanza facile usare uno stile funzionale in esso ... e un collega di stile non funzionale può cambiarlo facilmente in non funzionante
Mike Stone

1
Sì, Mike, se vuoi programmare in uno stile funzionale, Ruby è un enorme miglioramento rispetto a Java. Stavo usando Java solo per esagerare e martellare il punto a casa.
Chris Vest

Quindi, poiché D ha funzioni pure, chiameresti D un linguaggio funzionale? digitalmars.com/d/2.0/function.html#pure-functions
Peter Burns,

3
Molte persone considerano i linguaggi funzionali Lisp e Scheme, in gran parte a causa dell'uso pervasivo di funzioni anonime. Eppure, mancano di funzioni pure garantite. Limitare il termine alle lingue che supportano le funzioni pure sembra troppo restrittivo.
skymt

13

Ruby dovrà soddisfare i seguenti requisiti per essere "VERAMENTE" funzionale.

Valori immutabili: una volta impostata una “variabile”, non può essere modificata. In Ruby, questo significa che devi effettivamente trattare le variabili come costanti. Non è completamente supportato nella lingua, dovrai congelare ogni variabile manualmente.

Nessun effetto collaterale: quando viene passato un dato valore, una funzione deve sempre restituire lo stesso risultato. Questo va di pari passo con l'avere valori immutabili; una funzione non può mai prendere un valore e modificarlo, poiché ciò provocherebbe un effetto collaterale tangenziale alla restituzione di un risultato.

Funzioni di ordine superiore: sono funzioni che consentono funzioni come argomenti o utilizzano funzioni come valore restituito. Questa è, probabilmente, una delle caratteristiche più critiche di qualsiasi linguaggio funzionale.

Currying: abilitato dalle funzioni di ordine superiore, il currying trasforma una funzione che accetta più argomenti in una funzione che accetta un argomento. Questo va di pari passo con l'applicazione della funzione parziale, che sta trasformando una funzione con più argomenti in una funzione che richiede meno argomenti rispetto a quanto aveva fatto in origine.

Ricorsione: ciclo chiamando una funzione dall'interno di se stessa. Quando non si ha accesso a dati modificabili, la ricorsione viene utilizzata per creare e concatenare la costruzione dei dati. Questo perché il looping non è un concetto funzionale, poiché richiede il passaggio di variabili per memorizzare lo stato del loop in un dato momento.

Valutazione pigra o valutazione ritardata : ritardare l'elaborazione dei valori fino al momento in cui è effettivamente necessaria. Se, ad esempio, hai del codice che ha generato un elenco di numeri di Fibonacci con la valutazione pigra abilitata, questo non verrebbe effettivamente elaborato e calcolato fino a quando uno dei valori nel risultato non fosse richiesto da un'altra funzione, come put.

Proposta (solo un pensiero) Sarei fantastico avere un qualche tipo di definizione per avere una modedirettiva per dichiarare i file con paradigma funzionale, esempio

modalità 'funzionale'


2
Prego. Vorrei invitarvi a leggere sui linguaggi funzionali. Lisp è il nonno di tutte le lingue funzionali, ML (CAML) ed Erlang / Elixir. Cambia davvero la tua prospettiva delle cose. Non sono di gran lunga un esperto, ma uno studente costante di informatica ama leggere e imparare cose nuove.
Elias Perez

Risposta ben organizzata. Mi sarebbe piaciuto approfondire il modo in cui Ruby supporta queste cose. Credo che le funzioni di ordine superiore, il currying e la ricorsione siano tutte supportate / possibili in ruby, per favore correggimi se sbaglio.
Michael Dorst


4

Ruby è un linguaggio orientato agli oggetti, che può supportare altri paradigmi (funzionale, imperativo, ecc.). Tuttavia, poiché tutto in Ruby è un oggetto, è principalmente un linguaggio OO.

esempio:

"hello" .reverse () = "olleh", ogni stringa è un'istanza di un oggetto stringa e così via.

Leggi qui o qui


Non ho mai capito come "tutto è un oggetto" renda Ruby più OO. Sono d'accordo sul fatto che Ruby sia principalmente OO, ma "tutto è un oggetto" in realtà significa solo che non ci sono tipi "primitivi", il che ha pochissima influenza sulla capacità dello sviluppatore di scrivere programmi in stile OO, data che l'esistenza di primitivi tipi generalmente significa solo che ci sono quattro o cinque tipi che non hanno metodi.
Michael Dorst

4

Dipende dalla tua definizione di "linguaggio funzionale". Personalmente, penso che il termine stesso sia piuttosto problematico se usato come assoluto. Ci sono più aspetti dell'essere un "linguaggio funzionale" che semplici caratteristiche del linguaggio e la maggior parte dipende da dove stai guardando. Ad esempio, la cultura che circonda la lingua è piuttosto importante a questo proposito. Incoraggia uno stile funzionale? E le biblioteche disponibili? Ti incoraggiano a usarli in modo funzionale?

La maggior parte delle persone chiamerebbe Scheme un linguaggio funzionale, per esempio. Ma per quanto riguarda Common Lisp? A parte il problema dello spazio dei nomi multiplo / singolo e l'eliminazione delle chiamate di coda garantita (che supportano anche alcune implementazioni CL, a seconda delle impostazioni del compilatore), non c'è molto che renda Scheme un linguaggio più adatto alla programmazione funzionale rispetto a Common Lisp, e ancora, la maggior parte dei Lispers non chiamerebbe CL un linguaggio funzionale. Perché? Perché la cultura che lo circonda dipende in larga misura dalle caratteristiche imperative di CL (come la macro LOOP, ad esempio, che la maggior parte degli Schemer probabilmente disapproverebbe).

D'altra parte, un programmatore C potrebbe considerare CL un linguaggio funzionale. La maggior parte del codice scritto in qualsiasi dialetto Lisp è certamente molto più funzionale nello stile del solito blocco di codice C, dopotutto. Allo stesso modo, Scheme è un linguaggio imperativo rispetto a Haskell. Pertanto, non penso che possa mai esserci una risposta affermativa / negativa. Se chiamare un linguaggio funzionale o meno dipende fortemente dal tuo punto di vista.


In che modo Haskell non è un linguaggio puramente funzionale? O che ne dici di Miranda (un linguaggio di programmazione funzionale meno noto)? course.cs.washington.edu/courses/cse505/99au/functional/… "Haskell è un linguaggio funzionale puro standard,"
barlop

2

Ruby non è nemmeno un linguaggio multi-paradigma, credo. Il multi-paradigma tende ad essere usato da persone che vogliono etichettare la loro lingua preferita come qualcosa che è utile in molte aree diverse.

Descriverei che Ruby è un linguaggio di scripting orientato agli oggetti. Sì, le funzioni sono oggetti di prima classe (più o meno), ma questo non lo rende davvero un linguaggio funzionale. IMO, potrei aggiungere.


4
Il tipo di linguaggio è definito dagli stili di programmazione che supporta; che, a sua volta, è deciso dalle caratteristiche che ha. Funzioni di prima classe e anonime = programmazione funzionale minima. Ruby supporta la programmazione OO ma non la richiede: non è mai necessario definire una classe. Quindi, multi-paradigma.
skymt

2

La ricorsione è comune nella programmazione funzionale. Quasi tutti i linguaggi supportano la ricorsione, ma gli algoritmi ricorsivi sono spesso inefficaci se non esiste un'ottimizzazione delle chiamate di coda (TCO).

I linguaggi di programmazione funzionali sono in grado di ottimizzare la ricorsione in coda e possono eseguire tale codice in uno spazio costante. Alcune implementazioni di Ruby ottimizzano la ricorsione in coda, altre no, ma in generale le implementazioni di Ruby non sono richieste per fare il TCO. Vedi Ruby esegue l'ottimizzazione delle chiamate di coda?

Quindi, se scrivi uno stile funzionale Ruby e fai affidamento sul TCO di qualche implementazione particolare, il tuo codice potrebbe essere molto inefficace in un altro interprete Ruby. Penso che questo sia il motivo per cui Ruby non è un linguaggio funzionale (né lo è Python).


Il TCO è interessante, perché cambia essenzialmente il comportamento del programma. In alcuni casi, questo non è visibile al programma, ma in altri casi lo è, ad esempio, backtrace delle eccezioni. Pertanto, non è sempre un'ottimizzazione appropriata.
ioquatix

2

A rigor di termini, non ha senso descrivere un linguaggio come "funzionale"; la maggior parte dei linguaggi è in grado di programmare funzioni. Anche il C ++ lo è.

Lo stile funzionale è più o meno un sottoinsieme di caratteristiche del linguaggio imperativo, supportato con zucchero sintattico e alcune ottimizzazioni del compilatore come l'immutabilità e l'appiattimento della ricorsione della coda,

Quest'ultimo è probabilmente un tecnicismo minore specifico dell'implementazione e non ha nulla a che fare con il linguaggio effettivo. Il compilatore x64 C # 4.0 esegue l'ottimizzazione della ricorsione in coda, mentre quello x86 non lo fa per qualche stupida ragione.

Lo zucchero sintattico di solito può essere lavorato in un modo o nell'altro, specialmente se il linguaggio ha un precompilatore programmabile (cioè #define del C).

Potrebbe essere leggermente più significativo chiedere "il linguaggio __ supporta la programmazione imperativa?", E la risposta, ad esempio con Lisp, è "no".


1

Per favore, dai un'occhiata all'inizio del libro: "A-Great-Ruby-eBook" . Discute l'argomento molto specifico che stai chiedendo. Puoi fare diversi tipi di programmazione in Ruby. Se vuoi programmare come funzionalmente, puoi farlo. Se vuoi programmare in modo imperativo, puoi farlo. È una questione di definizione quanto sia funzionale Ruby alla fine. Si prega di consultare la risposta dell'utente camflan.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.