Демистификация функционального программирования (часть 2) - необходимость неизменности

С возвращением! Тем, кто не читал предыдущий блог этой серии, я бы порекомендовал пройти Часть 1 (чтение 5 минут) для лучшего понимания!

Что такое неизменность и изменчивость?

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

В java вы можете рассматривать final как неизменяемый, тогда как в scala все поля, объявленные как «val», являются неизменяемыми, а «var» - изменяемыми!

Строки также неизменны в Java.

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

Не будем здесь углубляться в языковые особенности!

Почему неизменность?

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

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

Сделайте переменные неизменяемыми, если нет веской причины не делать этого.

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

Я отвечу на этот вопрос через некоторое время, прежде чем сообщу одну вещь, которая В языке функционального программирования «Все« оценивает »значение». Это означает, что даже оператор if else будет возвращать вам объект!

На первом рисунке мы используем изменяемые поля «flag», которых мы могли бы легко избежать, используя концепцию, согласно которой в функциональном программировании все оценивается как значение. Таким образом, условие if else возвращает выражение true / false, которое хранится в неизменяемом поле ‘flag’ на втором изображении.

Откажитесь от своей самой любимой переменной ‘i’, пока не поздно! Еще один пример того, как избежать циклов for. Если вы используете функцию потока в java 8, вы поймете приведенные ниже коды, в любом случае я бы попытался объяснить это! Итак, у нас есть список, и мы хотим увеличить его значения на 2 (добавить 2 к каждому значению).

Первое изображение говорит само за себя, и основной подход к этому, переходя ко второму фрагменту кода, мы использовали функцию 'map', которая является не чем иным, как функцией преобразования в scala. Помещение карты в список переносит нас внутрь списка, предоставляя доступ к каждому значению, которое здесь представлено как '_' (подчеркивание). Итак, подчеркивание - это наши целочисленные значения, которые есть в списке по одному. Чтобы решить нашу проблему, мы просто выполняем (_ + 2), который дает нам требуемый результат, создавая newList!

Вы также можете использовать «map» в Java 8, но вам нужно сделать дополнительный шаг по преобразованию списка в потоки, чтобы неизменяемый код в java выглядел так:

final List newList= list.stream().map(value -> value + 2).collect(Collectors.toList());

Последний пример - сумма чисел от 1 до 10-

val sum10 = (1 until 10).foldLeft(0){
  case (sum,curr) => sum + curr
}

Здесь (от 1 до 10) будет указан диапазон. FoldLeft - это проходимая функция, позволяющая принимать значения слева направо с параметром по умолчанию ( 0, то есть сумма здесь). Как видно из приведенного выше фрагмента кода, мы не использовали объявление изменяемого поля SUM.

Вывод:

Если вы хотите писать параллельный код, используя большую часть вычислительной мощности, и хотите поточно-ориентированный способ - неизменяемость - это ответ!

Если у вас есть вопросы относительно того, как преобразовать изменяемый сценарий в неизменяемый, вы можете связаться со мной по моему дескриптору LinkedIn! :)