Чи можливе функціональне програмування на Java? [зачинено]


42

Я переглядав книжковий магазин Amazon.com і натрапив на книгу "Функціональне програмування для розробників Java" .

Я знаю кілька дуже базових функціональних програмувань і займаюся програмуванням на Java протягом 3 років.

Мені хотілося б знати, чи можливо на Java можливо функціональне програмування?


2
Стиль можливий, але його багатослівність може бути занадто сильною для синтаксису Java: funkcionaljava.org
Юрій Зубарев

7
@nCdy Навіщо перевіряти JRuby? будь ласка, надайте більше пояснень.
Хірон

1
перевірити groovy :-)
Ant's

6
Я думаю, що саме таке питання викликає відмінність між Java-мовою та Java-платформою.
Томас Оуенс

2
@ ThorbjørnRavnAndersen: Що змушує вас думати, що "функціональне програмування" визначається "лінивою оцінкою"? Це здається дивним прикладом для вибору ...
Іоанн Варфоломій

Відповіді:


70

Це залежить від того, що ви маєте на увазі під «функціональним програмуванням» та під «можливим».

Ви, очевидно, можете реалізувати речі за функціональною парадигмою. Однак мова Java не забезпечує синтаксичний цукор для цього, тому деякі речі будуть в кращому випадку нудними, а інші - надзвичайно нечистими.

Аналогічно, ви можете дуже добре записати об'єктно-орієнтований код мовою, визнаною як не-OO, наприклад C.

Бібліотеки Java

Є бібліотеки, які можуть допомогти вам це зробити, вже зробивши для вас ніжку та заховавши таємні речі:

Це дозволить вам писати код Java з більш функціональним підходом і, можливо, більш звичним синтаксисом та семантикою, як ви могли очікувати від FP-компетентної мови. У межах розуму, тобто.

Мови JVM

І очевидно, що ви можете реалізувати функціональну мову поверх Java. Тоді ви зможете використовувати його як свою мову FP. Це трохи більш високий рівень абстракції, ніж те, про що ви просили, але відносно в контексті (хоча я тут трохи обманюю, правда).

Наприклад, перевірте:

Більш-менш функціональні мови JVM

Незважаючи на те, що вони можуть бути не такими, якими ви хочете, є кілька інших мов, перенесених на платформу Java, які можуть звільнити вас від порівняно не настільки цікавого характеру Java (так, призначений для каламбура) Java і вже дадуть більше гнучкість. Значні кандидати, такі як JRuby , Jython та Rhino (відповідно для Ruby , Python та JavaScript / ECMAScript ), також пропонують цікавий потенціал для функціонального програмування, хоча вони, напевно, не є дійсно функціональними мовами програмування за своєю природою. Котлін JetBrains ', хоча чітко визнаючи, що це не функціональна мова, він підтримує деякі функціональні конструкції, а також варто переглянути.

Подальше читання

Ви також можете прочитати або переглянути ці статті чи відео:


2
Зараз вихідний код Clojure розміщено на Github github.com/clojure/clojure
Chiron

@ Легенда 1982 року: Я був швидшим за ваш коментар, я вже змінив посилання на офіційний сайт clojure.org :) Але дякую за те, що ви так швидко це зробили! Приємно бачити, як люди швидко реагують.
haylem

Є також ABCL ( common-lisp.net/project/armedbear ), але я не маю уявлення, де він потрапляє на зрілий / не зрілий масштаб, і це звичайна реалізація Lisp.
Ватін

@Vatine: цікаво, абсолютно ніколи про нього не чув. Буде швидко переглянути і додати його.
хайлем

1
Я люблю термін "Тюрін Тарпіт" Алана Перліса за те, що він намагався зробити те, що може зробити язик (тому що це завершення), але тільки з таким болем і складністю, що не слід намагатися.
itsbruce

11

Я читаю згадану вами книгу. Це дійсно добре BTW.

Так, можна працювати на Java. Я не знаю, до якого ступеня ви можете цього досягти, але ви можете реалізувати багато функціональних ідіом програмування.

Однією з найважливіших речей є намагання кодувати ментальність "Не мутуйте стани".

Наприклад, ви використовуєте остаточне ключове слово для досягнення незмінності. Якщо ви збираєтеся використовувати структуру даних, то вам слід ввести код у незмінні структури даних. Бібліотека Google Guava вже робить це.

Також для одночасного програмування можна покластися на рамку Akka (модель актора).

Варто зазначити, що байт-код JVM не підтримує (принаймні, поки) оптимізацію Tail-call, дуже важливу особливість функціональних мов програмування.


"Варто зазначити, що байт-код JVM не підтримує (принаймні, поки) оптимізацію Tail-call, дуже важливу особливість функціональних мов програмування.": Що ви маєте на увазі? У Scala є TCO.
Джорджіо

@Giorgio: Scala робить TCO під час компіляції.
scrwtp

@scrwtp: Чи є за це покарання за ефективність? Або які недоліки TCO часу компіляції?
Джорджо

@Giorgio: Я мав на увазі те, що байт-код Java не підтримує його, як і в хіроні. Функціональні мови працюють навколо нього, компілюючи хвостові рекурсивні виклики в петлі, але це особливість компілятора байт-кодів мови->, а не JVM.
scrwtp

@scrwtp: Відповідь Хірона зазначає "Варто згадати, що байт-код JVM не підтримує (принаймні поки що) оптимізацію Tail-call, що є дуже важливою функцією для функціональних мов програмування." тому це звучить, як реалізація функціональної мови на JVM накладається штраф, але (і ми, мабуть, погоджуємося з цим), це не відповідає дійсності, оскільки оптимізація хвостових викликів може бути змодельована у складеному коді. Тож я погоджуюся з твердженням Хірона, але вважаю це дещо оманливим.
Джорджо

6

Так, це, безумовно, можливо так само, як це можливо в будь-якій комбінації середовища та мови виконання. Ви навіть можете змусити його працювати досить добре, якщо знаєте, що робите.

Не впевнений, наскільки це розумно. Зокрема, пам’ятайте, що це не особливо ідіоматично (тобто це буде виглядати дуже дивно, вам доведеться робити якісь нетрадиційні речі і плутати людей, які звикли регулярно використовувати Java)

Ви отримаєте якийсь дивний код, наприклад, для визначення нової функції:

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

Для функціонального програмування вам зазвичай потрібно:

  • Функції першого класу - легко створити в Java шляхом визначення абстрактного класу або інтерфейсу, який представляє вашу "Функцію" і має метод "застосувати", який застосовує функцію до одного або декількох параметрів.
  • Закриття - створіть екземпляр вашого об’єкта функції вище із закритими значеннями, збереженими у заключних полях. Ви можете використовувати для цього анонімний внутрішній клас.
  • Бібліотека стандартних функцій вищого порядку - це складніше, проте ви все одно можете написати свій власний, щоб завантажити просту функціональну мову за кілька годин. Якщо ви хочете чогось більш фантазійного, ви можете переглянути інші функціональні бібліотеки, які люди створили на Java.

Так це можливо як вправа і навіть цікавий хобі-проект. Але ви дійсно хочете займатися серйозним функціональним програмуванням, зберігаючи переваги JVM / доступу до бібліотек Java, то Clojure , на мій погляд, є найкращим варіантом.

ps, оскільки ядро ​​Clojure насправді написано на Java, це насправді дуже цікавий приклад того, як робити функціональне програмування на Java, приховуючи брудні деталі за симпатичним новим сучасним синтаксисом мови. Clojure вихідний код є на GitHub для тих, хто цікавиться.


Цікаво, що я помітив, що остання версія IntelliJ IDEA складе ці анонімні матеріали в більш компактну форму для відображення в редакторі. Виконує пристойну роботу по приховуванню надмірної сучки. Звичайно, все це буде несуттєво прийшов Java 8.
Бен Харді

4

На Яві можливо бути дещо функціональним. Робити це дуже серйозно . Замість

myList.each { doSomething(it); }

У вас є щось на кшталт:

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

І якщо ви хочете справжнього функціонального програмування, із закриттями та функціями як об'єктами першого класу виберіть іншу мову. Scala, Clojure, Groovy усі працюють на JVM і можуть взаємодіяти зі застарілими класами Java. .


Функціональне програмування - це не використання блоків замість анонімних класів. У Java 8 є блоки, тому ваш розміщений код буде виглядати більш елегантно, але це не буде функціональним програмуванням.
Хірон

@ Легенд: Я це розумію, але, очевидно, не дуже добре пояснив це.
Кевін Клайн

це недогляд / недогляд. будь-якою мовою, ви повинні фактично визначити функцію ДЕЙШЕ, ви не можете пропустити цю частину. Отже, Java майже настільки ж стисла, що вам потрібно зробити, це зробити об'єкт Функції неанонімним. Ви можете зробити це: Функція f = нова функція () {public void do () {}}; .... тоді ... викликайте цю функцію .... myMethodToCallAFunction (Функція f) {f.do ()} ... це все, брати і броліни. змирися з цим.
Олександр Міллс

3

Відповідь є гучним "так, звичайно", але, на мою думку, однією з найважливіших особливостей багатьох функціональних мов є відмінна система типу. Ви ніколи не зможете самостійно керувати цим на Java.

Якщо ви хочете писати функціональні програми, але все ж залишатися з JVM, я можу порекомендувати серед звичайних підозрюваних Scala та Clojure подивитися на Frege . У Frege є система синтаксису та типу, яка дуже близька до Haskell, але програми переводяться безпосередньо на java-код і можуть взаємодіяти з іншим кодом java.


2

Ну, можливі всілякі речі. В C можна робити об'єктно-орієнтоване програмування; це просто не дуже гарна ідея.

Java не була розроблена для FP, тому якщо ви намагаєтеся робити все в чисто FP-стилі, у вас виникнуть проблеми. Ви будете боротися з мовою, а не працювати з нею. І не тільки мова - тут також є всі чудові безкоштовні бібліотеки Java. Так що не йдіть на чисту FP; візьміть деякі ідеї, що стоять за FP та інтегруйте їх у свій код Java, але розумійте, що ви не можете зробити це для всіх ідей.


0

Команда OpenJDK вас заохочує завантажити останні свої бінарні файли OpenJDK 8 і пограти з новими лямбда-виразами та новими функціональними ідіомами, введеними в API Collections (серед інших). Ви можете програмувати у чіткому функціональному стилі. Див. "Функціональне програмування на Java?" для порівняння колекцій JDK8 з ліцензіями перед Java8, такими як Guava, FunctionalJava та LambdaJ.


-3

Це може здатися можливим, але це не буде чистим функціональним програмуванням. Це може призвести до імперативного програмування.

Немає запитань, чому він має на увазі під можливим функціональним програмуванням, про яке згадує хайлем. Ось:

Це залежить від того, що ви маєте на увазі під «функціональним програмуванням» та під «можливим».

Функціональне програмування не може мати різні визначення або значення, хоча воно може мати багато пояснень.
Як і OOP, ми можемо запитати "що ви маєте на увазі під OOP?".
Однозначно пояснень буде багато, але це стосуватиметься лише однієї мети, цілі ООП.
Те саме стосується функціонального програмування .

Коли ми говоримо функціональне значення, програми складаються з функцій.
Роль функцій полягає у поверненні оцінюваного аргументу / параметра (аргумент змінний - це вираз, що прийшов при виклику функції, тоді як параметр - мінливий, який є частиною оголошення функції).

Також функції завжди будуть повертати той самий результат, коли передаються ті ж аргументи. Таким чином легше уникнути помилок або налагодити майбутні помилки. За допомогою функціонального програмування ми можемо уникнути таких побічних ефектів, як модифікація глобальної змінної.

Приклад у 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);

Приріст функції додає 1 значення кожному елементу всередині об'єкта і повертає результат. Значення myList не змінилося, але коли ми викликаємо функції, ми побачили додану цінність для елементів цього об’єкта.

Як моя відповідь на те, чи можливо на Java функціональне програмування? , Я вважаю, що справжнє функціональне програмування в java неможливо. Оскільки java справді розроблена як OOP, в якій вона розширює імперативне програмування та вдосконалює її для ремонту. Коли стан об'єкта, змінної тощо змінився тоді, це вже імперативне програмування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.