Возможно ли функциональное программирование в Java? [закрыто]


42

Я просматривал книжный магазин Amazon.com и наткнулся на книгу «Функциональное программирование для Java-разработчиков» .

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

Я хотел бы знать, возможно ли даже функциональное программирование в Java?


2
Стиль возможен, но его многословие может быть слишком большим, чтобы выдержать данный синтаксис Java: functionsjava.org
Юрий Зубарев

7
@nCdy Зачем проверять JRuby? пожалуйста, предоставьте больше объяснений.
Хирон

1
проверка заводной :-)
Муравьи

6
Я думаю, что именно такой вопрос поднимает различие между Java-языком и Java-платформой.
Томас Оуэнс

2
@ ThorbjørnRavnAndersen: С чего вы взяли, что «функциональное программирование» определяется как «ленивая оценка»? Кажется странным примером выбрать ...
Джон Варфоломей

Ответы:


70

Это зависит от того, что вы подразумеваете под «функциональным программированием» и «возможным».

Очевидно, вы можете реализовать вещи, следуя функциональной парадигме. Однако язык Java не предоставляет синтаксического сахара для него, поэтому некоторые вещи будут в лучшем случае утомительными, а некоторые другие будут чрезвычайно загадочными.

Точно так же вы можете очень хорошо написать объектно-ориентированный код на языке, который распознается как не-OO, например C.

Библиотеки Java

Существуют библиотеки, которые могут помочь вам сделать это, уже выполнив работу за вас и скрывая тайные вещи:

Это позволит вам писать код на Java с более функциональным подходом и, возможно, с более знакомым синтаксисом и семантикой, как вы ожидаете от FP-компетентного языка. В пределах разумного.

JVM Languages

И, очевидно, вы можете реализовать функциональный язык поверх Java. Так что вы можете использовать его в качестве языка FP. Это немного более высокий уровень абстракции, чем вы просили, но относительно в контексте (хотя я немного обманываю здесь, само собой разумеется).

Например, проверьте:

Более-менее функциональные языки JVM

Хотя они могут быть не совсем такими, как вы хотите, есть ряд других языков, которые были перенесены на платформу Java и которые могут освободить вас от относительно не столь увлекательной (да, каламбурной) природы Java и уже дать вам больше гибкость. Известные претенденты, такие как JRuby , Jython и Rhino (соответственно для Ruby , Python и JavaScript / ECMAScript ), также предлагают интересный потенциал для функционального программирования, хотя они, возможно, по сути не являются функциональными языками программирования. JetBrains ' Kotlinхотя он и признает, что это не функциональный язык, он поддерживает некоторые функциональные конструкции и также стоит посмотреть.

Дальнейшее чтение

Вы также можете прочитать или посмотреть эти статьи или видео:


2
Исходный код Clojure теперь размещен на Github github.com/clojure/clojure
Chiron

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

Есть также ABCL ( common-lisp.net/project/armedbear ), но я понятия не имею, где он находится в зрелом / не зрелом масштабе, и это реализация Common Lisp.
Vatine

@Vatine: интересно, никогда не слышал об этом. Быстро взглянем и добавим.
Хайлем

1
Я люблю термин Алана Перлиса «Тарпинг Тьюринга» за то, что он пытается сделать что-то, что может сделать язык (потому что он завершен по Тьюрингу ), но только с такой болью и сложностью, что не следует пытаться.
Брюс

11

Я читаю книгу, которую вы упомянули. Это действительно хорошо, кстати.

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

Одной из самых важных вещей является попытка кодирования с менталитетом «Не изменяй состояния».

Например, вы используете ключевое слово final для достижения неизменности. Если вы собираетесь использовать структуру данных, то вам следует кодировать в неизменяемых структурах данных. Библиотека Google Guava уже делает это.

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

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


«Стоит отметить, что байт-код JVM не поддерживает (по крайней мере, пока) оптимизацию Tail-call, очень важную функцию для функциональных языков программирования.»: Что вы имеете в виду? У Scala есть TCO.
Джорджио

@ Джорджио: Scala делает TCO во время компиляции.
scrwtp

@scrwtp: есть ли из-за этого снижение производительности? Или каковы недостатки TCO во время компиляции?
Джорджио

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

@scrwtp: ответ Хирона гласит: «Стоит упомянуть, что байт-код JVM не поддерживает (по крайней мере, пока) оптимизацию вызова хвоста, очень важную функцию для функциональных языков программирования». звучит так, будто реализация функционального языка в JVM наказывается, но (и мы, похоже, с этим согласны) это не так, поскольку оптимизацию хвостового вызова можно смоделировать в скомпилированном коде. Поэтому я согласен с заявлением Хирона, но считаю его немного вводящим в заблуждение.
Джорджио

6

Да, это определенно возможно , точно так же, как это возможно в любой комбинации языка и среды выполнения, полной по Тьюрингу. Вы даже можете заставить его работать достаточно хорошо, если знаете, что делаете.

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

Вы получите странный код, например, для определения новой функции:

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

Для функционального программирования вам обычно требуется:

  • Функции первого класса - легко создавать в Java, определяя абстрактный класс или интерфейс, который представляет вашу «функцию» и имеет метод «apply», который применяет функцию к одному или нескольким параметрам.
  • Закрытия - создайте экземпляр вашего функционального объекта выше с закрытыми значениями, сохраненными в конечных полях. Для этого вы можете использовать анонимный внутренний класс.
  • Библиотека стандартных функций высшего порядка - это сложнее, но вы все равно можете написать свою собственную, чтобы загрузить простой функциональный язык за несколько часов. Если вы хотите что-то более необычное, вы можете проверить другие функциональные библиотеки, которые люди создали в Java.

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

ps, поскольку ядро ​​Clojure на самом деле написано на Java, это на самом деле очень интересный пример того, как выполнять функциональное программирование на Java, скрывая при этом грязные детали за хорошим новым синтаксисом современного языка. Исходный код Clojure находится на GitHub для тех, кто заинтересован.


Интересно, что я заметил, что последняя версия IntelliJ IDEA свернет эти анонимные сообщения в более компактную форму для отображения в редакторе. Делает приличную работу, прячет лишнюю крошку. Конечно все это будет неактуально на Java 8.
Бен Харди

4

В Java можно быть несколько функциональным. Это серьезно больно . Вместо того

myList.each { doSomething(it); }

У вас есть что-то вроде:

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

И если вы хотите по-настоящему функциональное программирование с замыканиями и функциями в качестве объектов первого класса, выберите другой язык. Scala, Clojure, Groovy все работают на JVM и могут взаимодействовать с унаследованными классами Java. ,


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

@Legend: Я понимаю это, но, видимо, плохо объяснил.
Кевин Клайн

это недосмотр. с любым языком вы должны фактически определить функцию КУДА-ТО, вы не можете пропустить эту часть. Так что Java почти такой же лаконичный, все, что вам нужно сделать, это сделать объект Function неанонимным. Вы можете сделать это: Function f = new Function () {public void do () {}}; .... тогда ... вызовите эту функцию .... myMethodToCallAFunction (Function f) {f.do ()} ... вот и все, братаны и бролини. иметь дело с этим.
Александр Миллс

3

Ответ - «да, конечно», но, на мой взгляд, одной из наиболее важных функций во многих функциональных языках является превосходная система типов. Вы никогда не сможете управлять этим на Java самостоятельно.

Если вы хотите писать функциональные программы и при этом оставаться в JVM, я могу порекомендовать среди обычных подозреваемых Scala и Clojure взглянуть на Фреге . Фреге имеет систему синтаксиса и типов, которая очень близка к Haskell, но программы переводятся непосредственно в код Java и могут взаимодействовать с другим кодом Java.


2

Ну, все возможно. Возможно сделать объектно-ориентированное программирование на C; это просто не очень хорошая идея.

Java не была разработана для FP, поэтому, если вы пытаетесь сделать все в стиле чисто FP, у вас будут проблемы. Вы будете бороться с языком, а не работать с ним. И не только язык - здесь также есть все замечательные бесплатные библиотеки Java. Так что не переходите на чистый FP; возьмите некоторые идеи, лежащие в основе FP, и интегрируйте их в свой Java-код, но понимайте, что вы не можете сделать это со всеми идеями.


0

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


-3

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

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

Это зависит от того, что вы подразумеваете под «функциональным программированием» и «возможным».

Функциональное программирование не может иметь разных определений или значений, хотя может иметь много объяснений.
Как ООП, мы можем спросить «что вы подразумеваете под ООП?».
Определенно будет много объяснений, но это будет относиться только к одной цели, цели ООП.
То же самое относится и к функциональному программированию .

Когда мы говорим функциональное значение, программы состоят из функций.
Роль функций состоит в том, чтобы возвращать вычисленный аргумент / параметр (аргумент переменная - это выражение, полученное при вызове функции, в то время как параметр переменная, которая является частью объявления функции).

Кроме того, функции всегда будут возвращать один и тот же результат при передаче одинаковых аргументов. Таким образом, легче избежать ошибок или отладить будущие ошибки. С помощью функционального программирования мы можем избежать побочных эффектов, таких как изменение глобальной переменной.

пример в 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 действительно разработан, чтобы быть ООП, в котором он расширяет императивное программирование и улучшает его для удобства обслуживания. Когда состояние объекта, переменной и т. Д. Изменилось, это уже является обязательным программированием.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.