Ist funktionale Programmierung in Java möglich? [geschlossen]

42

Ich habe im Amazon.com Bookstore gestöbert und bin auf das Buch "Functional Programming for Java Developers" gestoßen .

Ich kenne einige sehr grundlegende Funktionen und programmiere seit 3 ​​Jahren in Java.

Ich würde gerne wissen, ob Functional Programming überhaupt in Java möglich ist.

Vinoth Kumar CM
quelle
2
Der Stil ist möglich, aber seine Ausführlichkeit könnte angesichts von Javas Syntax zu groß sein: functionaljava.org
Yuriy Zubarev
7
@nCdy Warum JRuby überprüfen? Bitte erläutern Sie dies genauer.
Chiron
1
Check groovy :-)
Ant
6
Ich denke, das ist die Art von Frage, die die Unterscheidung zwischen Java-der-Sprache und Java-der-Plattform aufwirft.
Thomas Owens
2
@ ThorbjørnRavnAndersen: Was lässt Sie denken, dass "funktionale Programmierung" durch "faule Auswertung" definiert wird? Es scheint ein seltsames Beispiel zu sein ...
John Bartholomew

Antworten:

70

Es kommt darauf an, was Sie unter "funktionaler Programmierung" und "möglich" verstehen.

Sie können offensichtlich Dinge implementieren, die einem funktionalen Paradigma folgen. Die Java-Sprache bietet jedoch nicht den syntaktischen Zucker dafür, so dass einige Dinge bestenfalls langweilig und andere äußerst arkane sein werden.

In ähnlicher Weise können Sie objektorientierten Code sehr gut in einer Sprache schreiben, die als nicht-OO erkannt wird, wie z. B. C.

Java-Bibliotheken

Es gibt Bibliotheken, die Ihnen dabei helfen können, indem sie bereits die Beinarbeit für Sie erledigen und die arkanen Dinge verstecken:

Auf diese Weise können Sie Java-Code mit einem funktionaleren Ansatz und möglicherweise vertrauterer Syntax und Semantik schreiben, wie Sie es von einer FP-fähigen Sprache erwarten würden. In Ordnung, das ist.

JVM-Sprachen

Und natürlich können Sie eine funktionale Sprache zusätzlich zu Java implementieren . Damit Sie diese dann als Ihre FP-Sprache verwenden können. Das ist ein bisschen mehr Abstraktion als gewünscht, aber relativ im Kontext (obwohl ich hier ein bisschen betrüge, zugegeben).

Schauen Sie sich zum Beispiel Folgendes an:

Mehr oder weniger funktionale JVM-Sprachen

Auch wenn sie möglicherweise nicht genau Ihren Wünschen entsprechen, gibt es eine Reihe anderer Sprachen, die auf die Java-Plattform portiert wurden und Sie möglicherweise von Javas relativ nicht so spaßiger Natur (ja, Wortspiel beabsichtigt) befreien und Ihnen bereits mehr bieten Flexibilität. Bemerkenswerte Konkurrenten wie JRuby , Jython und Rhino (jeweils für Ruby , Python und JavaScript / ECMAScript ) bieten ebenfalls ein interessantes Potenzial für funktionale Programmierung, obwohl sie von Natur aus keine wirklich funktionalen Programmiersprachen sind. JetBrains KotlinAuch wenn klar ist, dass es sich nicht um eine funktionale Sprache handelt, werden einige funktionale Konstrukte unterstützt, und es lohnt sich auch, einen Blick darauf zu werfen.

Weitere Lektüre

Vielleicht möchten Sie auch diese Artikel oder Videos lesen oder ansehen:

haylem
quelle
2
Der Quellcode von Clojure wird jetzt auf Github github.com/clojure/clojure
Chiron
@The Legend of 1982: Ich war schneller als Ihr Kommentar, ich habe bereits den Link zur offiziellen clojure.org-Seite geändert :) Aber danke, dass Sie es so schnell verstanden haben! Gut zu sehen, dass die Leute schnell reagieren.
Haylem
Es gibt auch ABCL ( common-lisp.net/project/armedbear ), aber ich habe keine Ahnung, wo es auf die reife / keine reife Skala fällt und es ist eine Common-Lisp-Implementierung.
Vatine
@Vatine: interessant, hatte absolut noch nie davon gehört. Werde einen kurzen Blick darauf werfen und es hinzufügen.
Haylem
1
Ich liebe Alan Perlis 'Begriff "Turing Tarpit", weil er versucht, etwas zu tun, was eine Languge kann (weil es vollständig ist), aber nur mit solchem ​​Schmerz und solcher Komplexität, dass es nicht versucht werden sollte.
Itsbruce
11

Ich lese das Buch, das Sie erwähnt haben. Es ist wirklich gut, übrigens.

Ja, es ist möglich, in Java funktionsfähig zu sein. Ich weiß nicht, bis zu welchem ​​Grad Sie es erreichen können, aber Sie können viele funktionale Programmiersprachen implementieren.

Eines der wichtigsten Dinge ist der Versuch, mit der Mentalität "Don't Mutate States" zu codieren.

Zum Beispiel verwenden Sie das Schlüsselwort final, um Unveränderlichkeit zu erreichen. Wenn Sie eine Datenstruktur verwenden möchten, sollten Sie unveränderliche Datenstrukturen codieren. Die Google Guava-Bibliothek tut dies bereits.

Auch für die gleichzeitige Programmierung können Sie sich auf das Akka-Framework (das Akteurmodell) verlassen.

Erwähnenswert ist, dass der JVM-Bytecode (zumindest noch) keine Tail-Call-Optimierung unterstützt, eine sehr wichtige Funktion für funktionierende Programmiersprachen.

Chiron
quelle
"Es ist erwähnenswert, dass der JVM-Bytecode (zumindest noch) keine Tail-Call-Optimierung unterstützt, eine sehr wichtige Funktion für funktionierende Programmiersprachen.": Was meinen Sie? Scala hat TCO.
Giorgio
@ Giorgio: Scala führt die TCO zur Kompilierungszeit durch.
Scrwtp
@scrwtp: Gibt es deswegen eine Leistungsminderung? Oder was sind die Nachteile der TCO während der Kompilierung?
Giorgio
@Giorgio: Was ich damit gemeint habe ist, dass Java-Bytecode es nicht nativ unterstützt, so wie es ursprünglich von Chiron angegeben wurde. Funktionale Sprachen umgehen das Problem und kompilieren rekursive Aufrufe in Schleifen. Dies ist jedoch eine Funktion des language-> bytecode-Compilers und nicht der JVM.
Scrwtp
@scrwtp: In der Antwort von Chiron heißt es: "Es ist erwähnenswert, dass der JVM-Bytecode (zumindest noch) keine Tail-Call-Optimierung unterstützt, eine sehr wichtige Funktion für funktionierende Programmiersprachen." Das Klingen einer Implementierung einer funktionalen Sprache in der JVM wird bestraft. Dies ist jedoch (und wir scheinen uns darin einig zu sein) nicht der Fall, da die Tail-Call-Optimierung im kompilierten Code simuliert werden kann. Ich stimme der Aussage von Chiron zu, finde sie aber etwas irreführend.
Giorgio
6

Ja, es ist definitiv möglich , genauso wie es in jeder Kombination aus Sprache und Ausführungsumgebung möglich ist. Sie können sogar eine recht gute Leistung erzielen, wenn Sie wissen, was Sie tun.

Ich bin mir nicht sicher, wie vernünftig es ist. Beachten Sie insbesondere, dass es nicht besonders idiomatisch ist (dh es wird sehr seltsam aussehen, Sie müssen einige unkonventionelle Dinge tun und Leute verwirren, die an reguläres Java gewöhnt sind).

Sie werden am Ende einen seltsam aussehenden Code haben, z. B. um eine neue Funktion zu definieren:

Function twoStrings=new Function() {
  public Object apply(Object param1) {
    // do something to param1 and return a result
  }
}

Für die funktionale Programmierung benötigen Sie normalerweise:

  • Erstklassige Funktionen - Einfach in Java zu erstellen, indem eine abstrakte Klasse oder Schnittstelle definiert wird, die Ihre "Funktion" darstellt und über eine "apply" -Methode verfügt, mit der die Funktion auf einen oder mehrere Parameter angewendet wird.
  • Abschlüsse - Erstellen Sie eine Instanz Ihres obigen Funktionsobjekts mit den in den letzten Feldern gespeicherten Abschlußwerten. Sie können dafür eine anonyme innere Klasse verwenden.
  • Eine Bibliothek mit Standardfunktionen höherer Ordnung - dies ist schwieriger, Sie können jedoch in wenigen Stunden Ihre eigene Bibliothek schreiben, um eine einfache funktionale Sprache zu booten. Wenn Sie etwas ausgefalleneres wollen, können Sie sich andere Funktionsbibliotheken ansehen, die in Java erstellt wurden.

Das ist also als Übung und sogar als interessantes Hobbyprojekt möglich. Aber Sie möchten wirklich ernsthafte funktionale Programmierung durchführen und gleichzeitig die Vorteile der JVM erhalten / auf Java-Bibliotheken zugreifen, dann ist Clojure meiner Meinung nach bei weitem die beste Option.

ps Da der Kern von Clojure tatsächlich in Java geschrieben ist, handelt es sich um ein sehr interessantes Fallbeispiel für die Funktionsprogrammierung in Java, bei dem die chaotischen Details hinter einer schönen neuen modernen Sprachsyntax verborgen bleiben. Clojure-Quellcode ist auf GitHub für Interessierte.

mikera
quelle
Interessanterweise ist mir aufgefallen, dass die neueste Version von IntelliJ IDEA diese anonymen Onesies zu einer kompakteren Form für die Anzeige im Editor zusammenfasst. Hat ein pretyt menschenwürdige Arbeit darin, die überflüssige Kruft zu verstecken. Natürlich wird all dies für Java 8 irrelevant sein.
Ben Hardy
4

Es ist möglich, in Java etwas funktionsfähig zu sein. Dies ist sehr schmerzhaft . Anstatt von

myList.each { doSomething(it); }

Sie haben so etwas wie:

myList.each(new Function() { public void do(Object arg) { something(); }})

Und wenn Sie eine echte funktionale Programmierung mit Verschlüssen und Funktionen als erstklassige Objekte wünschen, wählen Sie eine andere Sprache. Scala, Clojure und Groovy laufen alle auf der JVM und können mit älteren Java-Klassen interagieren. .

Kevin Cline
quelle
Bei der funktionalen Programmierung geht es nicht darum, Blöcke anstelle von anonymen Klassen zu verwenden. Java 8 wird Blöcke enthalten, sodass Ihr veröffentlichter Code eleganter aussieht, aber keine funktionale Programmierung sein wird.
Chiron
@Legend: Ich verstehe das, habe es aber offensichtlich nicht gut erklärt.
Kevin Cline
Das ist Versehen / Versehen. Für jede Sprache muss die Funktion "Irgendwo" definiert werden. Dieser Teil kann nicht übersprungen werden. Damit Java fast so präzise ist, müssen Sie das Function-Objekt nur nicht anonymisieren. Sie können dies tun: Function f = new Function () {public void do () {}}; .... dann ... rufe diese Funktion auf .... myMethodToCallAFunction (Function f) {f.do ()} ... das war's, bros und brolinis. Komm damit klar.
Alexander Mills
3

Die Antwort ist ein klares "Ja, natürlich", aber meiner Meinung nach ist eines der wichtigsten Merkmale in vielen funktionalen Sprachen das exzellente Typensystem. Sie werden dies in Java niemals selbst verwalten können.

Wenn Sie funktionierende Programme schreiben und dennoch bei der JVM bleiben möchten, kann ich unter den üblichen Verdächtigen Scala und Clojure empfehlen, sich Frege anzuschauen . Frege hat ein Syntax- und Typsystem, das Haskell sehr ähnlich ist, aber Programme werden direkt in Java-Code übersetzt und können mit anderem Java-Code interagieren.

Ingo
quelle
2

Nun, alles Mögliche ist möglich. Objektorientierte Programmierung ist in C möglich. Es ist einfach keine sehr gute Idee.

Java wurde nicht für FP entwickelt. Wenn Sie also versuchen, alles in einem reinen FP-Stil auszuführen, treten Probleme auf. Sie werden die Sprache bekämpfen, anstatt damit zu arbeiten. Und nicht nur die Sprache - es gibt auch all die wunderbaren kostenlosen Java-Bibliotheken. Entscheide dich also nicht für reine FP; Nehmen Sie einige der Ideen, die hinter FP stehen, und integrieren Sie sie in Ihren Java-Code. Verstehen Sie jedoch, dass Sie nicht alle Ideen damit bearbeiten können.

Mike Baranczak
quelle
0

Sie werden vom OpenJDK-Team ermutigt, die neuesten OpenJDK 8-Binärdateien herunterzuladen und mit den neuen Lambda-Ausdrücken und den neuen funktionalen Idiomen zu experimentieren, die unter anderem in der Collections-API eingeführt wurden. Sie können in einem klaren funktionalen Stil programmieren. Siehe "Funktionale Programmierung in Java?" für einen Vergleich von JDK8-Sammlungen mit vor Java8-Bibliotheken wie Guava, FunctionalJava und LambdaJ.

JohanN
quelle
-3

Es mag möglich erscheinen, aber es wird keine reine Funktionsprogrammierung sein. Dies kann zu einer zwingenden Programmierung führen.

Es ist keine Frage, warum er mit möglicher funktionaler Programmierung gemeint ist, wie von Haylem erwähnt. Hier ist es:

Es kommt darauf an, was Sie unter "funktionaler Programmierung" und "möglich" verstehen.

Die funktionale Programmierung kann keine unterschiedlichen Definitionen oder Bedeutungen haben, obwohl sie viele Erklärungen haben kann.
Können wir wie OOP fragen, "was meinst du mit OOP?".
Auf jeden Fall wird es viele Erklärungen geben, aber es wird sich nur um ein Ziel handeln, das Ziel von OOP.
Gleiches gilt für die funktionale Programmierung .

Wenn wir funktionale Bedeutung sagen, bestehen die Programme aus Funktionen.
Die Funktion besteht darin, ein ausgewertetes Argument / einen ausgewerteten Parameter zurückzugeben (Argument ist Variable ist der Ausdruck, der beim Aufrufen der Funktion angegeben wurde, während Parameter Variable ist, die Teil der Funktionsdeklaration ist).

Auch Funktionen geben immer dasselbe Ergebnis zurück, wenn dieselben Argumente übergeben werden. Auf diese Weise ist es einfacher, Fehler zu vermeiden oder zukünftige Fehler zu beheben. Durch funktionale Programmierung können wir Nebenwirkungen wie das Ändern globaler Variablen vermeiden.

Beispiel in JavaScript:

function increment(lis){
    return lis.map(
        function (x){
            return x+2;
        }
    );
}

var myList = [4, 7, 2, 3];
console.log(increment(myList));
console.log(myList);

Das Funktionsinkrement addiert 1 Wert zu jedem Element im Objekt und gibt das Ergebnis zurück. Der Wert von myList hat sich nicht geändert, aber wenn wir die Funktionen aufrufen, sehen wir den Mehrwert für Elemente dieses Objekts.

Wie ist meine Antwort auf Funktionale Programmierung in Java möglich? Ich glaube, dass es nicht möglich ist, echte funktionale Programmierung in Java zu haben. Weil Java wirklich als OOP konzipiert ist, in dem es die imperative Programmierung erweitert und es aus Gründen der Wartbarkeit verbessert. Wenn sich der Zustand eines Objekts, einer Variablen usw. geändert hat, ist dies bereits eine zwingende Programmierung.

L34Rn3R
quelle