Wikipedia dice che Ruby è un linguaggio funzionale, ma non sono convinto. Perché o perché no?
Wikipedia dice che Ruby è un linguaggio funzionale, ma non sono convinto. Perché o perché no?
Risposte:
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.
Is ruby a functional language?
e in una risposta diretta è un semplice no. Ruby è un linguaggio orientato agli oggetti con alcune caratteristiche funzionali.
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.
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.
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.
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 mode
direttiva per dichiarare i file con paradigma funzionale, esempio
modalità 'funzionale'
Ruby è un linguaggio multi-paradigma che supporta uno stile di programmazione funzionale.
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.
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.
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.
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).
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".
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.