Эта статья является частью серии о Java Forum Nord 2015 , конференции, которая состоялась в Ганновере, Германия. Ссылки на статьи о других беседах, которые я посетил, можно найти ниже.
Мне удавалось долго избегать темы функционального программирования, что было нехорошо. Когда в Java 8 были реализованы функциональные концепции, я подумал: «Он классный, теперь я не должен даже оставлять свой любимый язык программирования для изучения функционального программирования». Мне нравится использовать эти функции и я хочу больше узнать о функциональном программировании. Это дало мне более чем достаточно мотивации, чтобы посетить выступление Николь .
Николь начала свое выступление, спросив аудиторию, как они будут реализовывать приложение, которое суммирует квадратные числа от 1 до 10 в «старой доброй Java». Решением является следующий цикл for:
int sum = 0 ;
for ( int i = 1 ; i <= 10 ; i ++ ) {
sum = sum + i *i ;
}
Затем она написала тот же код на Java 8 (используя потоки):
IntUnaryOperator square = x ->; x *x ;
IntBinaryOperator add = (x,y ) -> x +y ;
IntStream. rangeClosed ( 1, 10 ). map (square ). reduce ( 0, add ) ; // 385
Это выглядит великолепно и более читабельно. Затем она показала то же самое в Хаскеле:
foldl (+) 0 (map (\x ->; x*x) [1..10]) -- 385
Есть так мало символов, я думаю, что это не может быть короче. Сразу после этого и нескольких других примеров кода я подумал: «Я должен выучить Haskell». Поскольку я не хочу приводить здесь все ее слайды, я просто беру один из ее примеров. Вы можете (и должны!) Взглянуть на остальные ее слайды .
Николь объяснила основные понятия функционального программирования. Функциональный язык должен включать в себя неизменность и чистые функции и относиться к ним как к первоклассным гражданам.
Итак, что такое неизменность ? Неизменяемый объект — это объект, который не изменяется. В Java это можно сделать, не написав методы set () и никогда не меняя атрибуты объекта. Вместо этого объекты создаются путем предоставления им всех атрибутов в конструкторе. Изменения реализуются путем создания совершенно новых объектов вместо изменения существующих. Это делает эти объекты потокобезопасными, потому что они имеют согласованное состояние в любое время. Кроме того, их намного проще создавать и тестировать.
Чистая функция просто представляет собой метод без побочных эффектов. Его вывод зависит только от входных параметров, который называется «ссылочная прозрачность». Если это так, то этот метод даст тот же результат при многократном вызове с одинаковыми параметрами. Каждый, кто отладил красивую, странную унаследованную кодовую базу, знает: эти методы гораздо проще понять, чем методы с побочными эффектами. Кроме того, они оптимизируются компилятором, потому что порядок выполнения является произвольным и результаты могут быть кэшированы.
Отношение к функциям как к первоклассным гражданам означает, что на функцию можно ссылаться и передавать по мере необходимости.
This makes it possible to use functions as parameters for other functions. These are called higher order functions, because they take other functions as parameters.
Using these concepts results in a number of advantages. There is no complicated modelling of status changes while debugging. Several optimizations can be done automatically. The code is more robust. Effects of code are isolated in one scope and need not be tracked throughout the codebase.
Other content of Java Forum Nord 2015
These are the talks I visited:
- Keynote by Adam Bien
- «Reflecting Software Architectures» by Stefan Zörner
- «Yes we scan — Software analysis with JQAssistant» by Dirk Mahler (blog post by Dirk Mahler himself)
- «Mastering legacy code in x simple steps» by Falk Sippach
- «Swimming upstream in the container revolution: Containerless Continuous Delivery» by Bert Jan Schrijver
- «Functional Programming in Java 8» by Nicole Rauch
- «where has my software architecture gone?» by Oliver Gierke