Risposta:
Wikipedia ha un ottimo articolo sulla programmazione funzionale con alcuni degli esempi che chiedi. @Konrad Rudolph ha già fornito il link all'articolo OOP .
Non penso che un paradigma sia un superinsieme dell'altro. Sono diverse prospettive sulla programmazione e alcuni problemi sono meglio risolti da una prospettiva e alcuni da un'altra.
La tua domanda è ulteriormente complicata da tutte le implementazioni di FP e OOP. Ogni lingua ha le sue stranezze che sono rilevanti per qualsiasi buona risposta alla tua domanda.
Rambling sempre più tangenziale:
Mi piace l'idea che un linguaggio come Scala cerchi di darti il meglio di entrambi i mondi. Temo che ti dia anche le complicazioni di entrambi i mondi.
Java è un linguaggio OO, ma la versione 7 ha aggiunto una funzione "prova con risorse" che può essere utilizzata per imitare una sorta di chiusura. Qui imita l'aggiornamento di una variabile locale "a" nel mezzo di un'altra funzione, senza renderla visibile a quella funzione. In questo caso la prima metà dell'altra funzione è il costruttore ClosureTry () e la seconda metà è il metodo close ().
public class ClosureTry implements AutoCloseable {
public static void main(String[] args) {
int a = 1;
try(ClosureTry ct = new ClosureTry()) {
System.out.println("Middle Stuff...");
a = 2;
}
System.out.println("a: " + a);
}
public ClosureTry() {
System.out.println("Start Stuff Goes Here...");
}
/** Interface throws exception, but we don't have to. */
public void close() {
System.out.println("End Stuff Goes Here...");
}
}
Produzione:
Start Stuff Goes Here...
Middle Stuff...
End Stuff Goes Here...
a: 2
Questo potrebbe essere utile per lo scopo previsto di aprire uno stream, scrivere nello stream e chiuderlo in modo affidabile, o semplicemente associare due funzioni in modo da non dimenticare di chiamare la seconda dopo aver fatto un po 'di lavoro tra di loro . Certo, è così nuovo e insolito che un altro programmatore potrebbe rimuovere il blocco try senza rendersi conto che stanno rompendo qualcosa, quindi attualmente è una specie di anti-pattern, ma interessante che possa essere fatto.
Puoi esprimere qualsiasi ciclo nella maggior parte delle lingue imperative come ricorsione. Oggetti e variabili possono essere resi immutabili. Le procedure possono essere scritte per ridurre al minimo gli effetti collaterali (anche se direi che una vera funzione non è possibile su un computer: il tempo necessario per l'esecuzione e le risorse del processore / disco / sistema che consuma sono inevitabili effetti collaterali). Alcuni linguaggi funzionali possono essere fatti per fare molte se non tutte le operazioni orientate agli oggetti. Non devono escludersi a vicenda, sebbene alcune lingue presentino limitazioni (come non consentire alcun aggiornamento delle variabili) che impediscono determinati schemi (come i campi mutabili).
Per me, le parti più utili della programmazione orientata agli oggetti sono il nascondimento dei dati (incapsulamento), il trattamento di oggetti abbastanza simili come gli stessi (polimorfismo) e la raccolta di dati e metodi che operano insieme su tali dati (oggetti / classi). L'ereditarietà può essere il fiore all'occhiello di OOP, ma per me è la parte meno importante e meno utilizzata.
Le parti più utili della programmazione funzionale sono l'immutabilità (token / valori anziché variabili), funzioni (senza effetti collaterali) e chiusure.
Non penso che sia orientato agli oggetti, ma devo dire che una delle cose più utili dell'informatica è la capacità di dichiarare un'interfaccia, quindi avere varie funzionalità e dati implementare quell'interfaccia. Mi piace anche avere alcuni dati mutabili con cui lavorare, quindi credo di non essere completamente a mio agio in linguaggi esclusivamente funzionali, anche se cerco di limitare la mutabilità e gli effetti collaterali in tutti i miei progetti di programma.