Czy programowanie funkcjonalne jest możliwe w Javie? [Zamknięte]

42

Przeglądałem Księgarnię Amazon.com i natknąłem się na książkę „Programowanie funkcjonalne dla programistów Java” .

Znam bardzo podstawowe programowanie funkcjonalne i programuję w Javie od 3 lat.

Chciałbym wiedzieć, czy programowanie funkcjonalne jest nawet możliwe w Javie?

Vinoth Kumar CM
źródło
2
Styl jest możliwy, ale jego gadatliwość może być zbyt duża, aby znieść składnię Javy: funkcjonjava.org
Yuriy Zubarev
7
@nCdy Dlaczego warto sprawdzić JRuby? proszę podać więcej wyjaśnień.
Chiron
1
sprawdź groovy :-)
Ant
6
Myślę, że jest to pytanie, które podnosi różnicę między językiem Java a platformą Java.
Thomas Owens
2
@ ThorbjørnRavnAndersen: Co sprawia, że ​​myślisz, że „programowanie funkcjonalne” jest zdefiniowane przez „leniwą ocenę”? Wydaje się dziwnym przykładem ...
John Bartholomew

Odpowiedzi:

70

Zależy to od tego, co rozumiesz przez „programowanie funkcjonalne” i „możliwe”.

Możesz oczywiście zaimplementować rzeczy zgodnie z paradygmatem funkcjonalnym. Jednak język Java nie zapewnia cukru syntaktycznego, więc niektóre rzeczy będą co najwyżej nużące, a niektóre inne będą wyjątkowo tajemnicze.

Podobnie możesz bardzo dobrze pisać kod zorientowany obiektowo w języku uznanym za język inny niż OO, np. C.

Biblioteki Java

Są biblioteki, które mogą ci w tym pomóc, wykonując już dla ciebie pracę nóg i ukrywając tajemne rzeczy:

Umożliwi to pisanie kodu Java z bardziej funkcjonalnym podejściem i być może bardziej znaną składnią i semantyczną, jak można się spodziewać po języku kompetentnym w FP. To znaczy w granicach rozsądku.

Języki JVM

I oczywiście możesz zaimplementować funkcjonalny język na Javie. Abyś mógł użyć tego jako języka FP. Co jest nieco wyższym poziomem abstrakcji niż to, o co prosiłeś, ale względnie w kontekście (choć tu trochę oszukuję, oczywiście).

Na przykład sprawdź:

Mniej lub bardziej funkcjonalne języki JVM

Chociaż mogą one nie być dokładnie tym, czego chcesz, istnieje wiele innych języków, które zostały przeniesione na platformę Java, które mogą uwolnić cię od stosunkowo mało zorientowanej na zabawę (tak, przeznaczonej z punktu widzenia gry) natury Javy i już dają ci więcej elastyczność. Znani pretendenci, tacy jak JRuby , Jython i Rhino (odpowiednio dla Ruby , Python i JavaScript / ECMAScript ) również oferują interesujący potencjał programowania funkcjonalnego, chociaż prawdopodobnie nie są to z natury funkcjonalne języki programowania. JetBrains ' Kotlin, choć wyraźnie uznaje, że nie jest to język funkcjonalny, obsługuje niektóre konstrukcje funkcjonalne i jest również warty obejrzenia.

Dalsza lektura

Możesz także przeczytać lub obejrzeć te artykuły lub filmy:

szaleństwa
źródło
2
Kod źródłowy Clojure jest teraz hostowany na Github github.com/clojure/clojure
Chiron
@ The Legend of 1982: Byłem szybszy niż twój komentarz, już zmieniłem link do oficjalnej strony clojure.org :) Ale dziękuję za szybkie złapanie tego! Dobrze widzieć, jak ludzie reagują szybko.
haylem,
Istnieje również ABCL ( common-lisp.net/project/armedbear ), ale nie mam pojęcia, gdzie wypada w dojrzałej / żadnej dojrzałej skali i jest to implementacja Common Lisp.
Vatine
@Vatine: ciekawe, absolutnie nigdy o tym nie słyszałem. Rzuci okiem i doda go.
haylem
1
Uwielbiam termin Alana Perlisa „Turing Tarpit” za próbę zrobienia czegoś, co język może zrobić (ponieważ jest to kompletny), ale tylko z takim bólem i złożonością, że nie należy tego próbować.
itsbruce
11

Czytam książkę, o której wspomniałeś. To naprawdę dobra BTW.

Tak, możliwe jest funkcjonowanie w Javie. Nie wiem do jakiego stopnia możesz to osiągnąć, ale możesz zaimplementować wiele funkcjonalnych idiomów programowania.

Jedną z najważniejszych rzeczy jest próba kodowania za pomocą mentalności „Nie mutuj stanów”.

Na przykład używasz ostatniego słowa kluczowego, aby uzyskać niezmienność. Jeśli zamierzasz użyć struktury danych, powinieneś kodować w niezmiennych strukturach danych. Biblioteka Google Guava już to robi.

Również w przypadku programowania współbieżnego możesz polegać na frameworku Akka (model aktora).

Warto wspomnieć, że kod bajtowy JVM nie obsługuje (przynajmniej jeszcze) Optymalizacji wywołania ogona, bardzo ważnej funkcji dla funkcjonalnych języków programowania.

Chiron
źródło
„Warto wspomnieć, że kod bajtowy JVM nie obsługuje (przynajmniej jeszcze) Optymalizacji wywołania ogona, bardzo ważnej funkcji dla funkcjonalnych języków programowania.”: Co masz na myśli? Scala ma całkowity koszt posiadania.
Giorgio
@Giorgio: Scala wykonuje TCO w czasie kompilacji.
scrwtp
@scrwtp: Czy z tego powodu istnieje utrata wydajności? Lub jakie są wady TCO w czasie kompilacji?
Giorgio
@Giorgio: Miałem na myśli to, że java bytecode nie obsługuje go natywnie, tak jak pierwotnie stwierdził Chiron. Języki funkcjonalne działają w ten sposób, kompilując wywołania rekurencyjne w pętle, ale jest to funkcja kompilatora language-> bytecode, a nie JVM.
scrwtp
@scrwtp: Odpowiedź Chirona brzmi: „Warto wspomnieć, że kod bajtowy JVM nie obsługuje (przynajmniej jeszcze) Optymalizacji wywołania ogona, bardzo ważnej funkcji dla funkcjonalnych języków programowania”. sprawianie, by brzmiało to jak implementacja języka funkcjonalnego na JVM, jest karane, ale (i wydaje się, że się z tym zgadzamy) nie jest to prawdą, ponieważ optymalizacja wywołania ogona może być symulowana w skompilowanym kodzie. Zgadzam się więc z oświadczeniem Chirona, ale wydaje mi się to nieco mylące.
Giorgio,
6

Tak, jest to zdecydowanie możliwe , w taki sam sposób, jak jest to możliwe w dowolnej kombinacji języka / środowiska wykonawczego Turing. Możesz nawet sprawić, by działał całkiem dobrze, jeśli wiesz, co robisz.

Nie jestem jednak pewien, czy to rozsądne. W szczególności pamiętaj, że nie jest to szczególnie idiomatyczne (tj. Będzie wyglądać bardzo dziwnie, będziesz musiał robić niekonwencjonalne rzeczy i dezorientować ludzi przyzwyczajonych do zwykłej Javy)

Otrzymasz dziwnie wyglądający kod, np. W celu zdefiniowania nowej funkcji:

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

Do programowania funkcjonalnego zwykle potrzebujesz:

  • Funkcje pierwszej klasy - łatwe do utworzenia w Javie poprzez zdefiniowanie abstrakcyjnej klasy lub interfejsu, który reprezentuje „Funkcję” i ma metodę „zastosuj”, która stosuje funkcję do jednego lub większej liczby parametrów.
  • Zamknięcia - utwórz instancję swojego obiektu funkcji powyżej z wartościami zamkniętymi przechowywanymi w końcowych polach. Możesz do tego użyć anonimowej klasy wewnętrznej.
  • Biblioteka standardowych funkcji wyższego rzędu - jest to trudniejsze, jednak nadal możesz napisać własny, aby w ciągu kilku godzin załadować prosty język funkcjonalny. Jeśli chcesz czegoś bardziej wyszukanego, możesz sprawdzić inne funkcjonalne biblioteki, które ludzie zbudowali w Javie.

Jest to więc możliwe jako ćwiczenie, a nawet ciekawy projekt hobby. Ale naprawdę chcesz poważnie programować funkcjonalnie, zachowując zalety JVM / dostęp do bibliotek Java, więc moim zdaniem Clojure jest zdecydowanie najlepszą opcją.

ps, ponieważ rdzeń Clojure jest w rzeczywistości napisany w Javie, jest to bardzo interesujący przykład tego, jak robić funkcjonalne programowanie w Javie, jednocześnie ukrywając bałagan w ładnej, nowoczesnej składni języka. Dla zainteresowanych zainteresowanych kod źródłowy Clojure znajduje się na GitHub .

mikera
źródło
Co ciekawe, zauważyłem, że najnowsza wersja IntelliJ IDEA złoży te anonimowe pliki w bardziej zwartą formę do wyświetlania w edytorze. Wykonuje porządną robotę ukrywania zbędnego cruftu. Oczywiście wszystko to nie będzie miało znaczenia, jeśli Java 8
Ben Hardy
4

W Javie można być nieco funkcjonalnym. Jest to bardzo bolesne . Zamiast

myList.each { doSomething(it); }

Masz coś takiego:

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

A jeśli chcesz prawdziwego programowania funkcjonalnego z zamknięciami i funkcjami jako obiektami pierwszej klasy, wybierz inny język. Scala, Clojure, Groovy działają na JVM i mogą współpracować ze starszymi klasami Java. .

Kevin Cline
źródło
Programowanie funkcjonalne nie polega na użyciu bloków zamiast anonimowych klas. Java 8 będzie zawierała bloki, więc opublikowany kod będzie wyglądał bardziej elegancko, ale nie będzie to programowanie funkcjonalne.
Chiron
@Legend: Rozumiem to, ale najwyraźniej nie wyjaśniłem tego dobrze.
kevin cline
jest to niedopatrzenie / niedopatrzenie. w dowolnym języku musisz zdefiniować funkcję GŁÓWNIE, nie możesz pominąć tej części. Tak więc Java jest prawie tak zwięzła, wszystko, co musisz zrobić, to uczynić obiekt Function anonimowym. Możesz to zrobić: Funkcja f = nowa funkcja () {public void do () {}}; .... następnie ... wywołaj tę funkcję .... myMethodToCallAFunction (Function f) {f.do ()} ... to wszystko, bros i brolinis. sobie z tym poradzić.
Alexander Mills,
3

Odpowiedź brzmi „tak, oczywiście”, ale moim zdaniem jedną z najważniejszych cech wielu języków funkcjonalnych jest doskonały system pisma. Nigdy nie będziesz w stanie samodzielnie zarządzać tym w Javie.

Jeśli chcesz pisać programy funkcjonalne, a mimo to pozostać przy JVM, mogę polecić Scalie i Clojureowi, jak zwykle, podejrzenie Frege . Frege ma system składni i typów, który jest bardzo zbliżony do Haskell, ale programy są tłumaczone bezpośrednio na kod java i mogą wchodzić w interakcje z innym kodem java.

Ingo
źródło
2

Cóż, możliwe są różne rzeczy. Możliwe jest programowanie obiektowe w C; to po prostu niezbyt dobry pomysł.

Java nie została zaprojektowana dla FP, więc jeśli próbujesz robić wszystko w stylu czysto FP, będziesz mieć problemy. Będziesz walczył z językiem, zamiast z nim pracować. I to nie tylko język - są też wszystkie wspaniałe bezpłatne biblioteki Java. Więc nie wybieraj czystego FP; zapoznaj się z niektórymi pomysłami związanymi z FP i zintegruj je ze swoim kodem Java, ale zrozum, że nie możesz tego zrobić dla wszystkich pomysłów.

Mike Baranczak
źródło
0

Zespół OpenJDK zachęca Cię do pobierania najnowszych plików binarnych OpenJDK 8 i zabawy z nowymi wyrażeniami lambda i nowymi funkcjonalnymi idiomami wprowadzonymi w API kolekcji (między innymi). Możesz programować w przejrzystym, funkcjonalnym stylu. Zobacz „Programowanie funkcjonalne w Javie?” do porównania kolekcji JDK8 z bibliotekami Java w wersjach wcześniejszych, takich jak Guava, FunctionalJava i LambdaJ.

JohanN
źródło
-3

Może się to wydawać możliwe, ale nie będzie to czysto funkcjonalne programowanie. Może to prowadzić do programowania imperatywnego.

Nie ma pytania, dlaczego miał na myśli możliwe programowanie funkcjonalne, o którym wspomniał Haylem. Oto on:

Zależy to od tego, co rozumiesz przez „programowanie funkcjonalne” i „możliwe”.

Programowanie funkcjonalne nie może mieć różnych definicji ani znaczenia, choć może mieć wiele wyjaśnień.
Podobnie jak OOP, możemy zapytać „co masz na myśli przez OOP?”.
Na pewno będzie wiele wyjaśnień, ale będzie to dotyczyło tylko jednego celu, celu OOP.
To samo dotyczy programowania funkcjonalnego .

Kiedy mówimy o znaczeniu funkcjonalnym, programy składają się z funkcji.
Rolą funkcji jest zwrócenie wartościowanego argumentu / parametru (argument jest zmienny, to wyrażenie pojawiło się podczas wywoływania funkcji, podczas gdy parametr jest zmienny, który jest częścią deklaracji funkcji).

Również funkcje zawsze zwracają ten sam wynik po przekazaniu tych samych argumentów. W ten sposób łatwiej jest unikać błędów lub debugować przyszłe błędy. Programując funkcjonalnie możemy uniknąć efektów ubocznych, takich jak modyfikacja zmiennej globalnej.

przykład w 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);

Przyrost funkcji dodaje 1 wartość do każdego elementu wewnątrz obiektu i zwraca wynik. Wartość myList nie zmieniła się, ale kiedy wywołujemy funkcje, zauważyliśmy wartość dodaną do elementów tego obiektu.

Czy moja odpowiedź na pytanie Czy programowanie funkcjonalne jest możliwa w Javie? , Uważam, że nie jest możliwe posiadanie prawdziwego programowania funkcjonalnego w Javie. Ponieważ Java jest naprawdę zaprojektowana jako OOP, w której rozszerza imperatywne programowanie i poprawia ją w celu utrzymania. Gdy stan obiektu, zmiennej itp. Ulegnie zmianie, jest to już programowanie imperatywne.

L34Rn3R
źródło