Последние пару недель я работал с Clojure. Я создал крестики-нолики и в настоящее время работаю над инструментом для ведения блога. В начале я много боролся, потому что Clojure — мой первый язык функционального программирования. Мне казалось, что я сделал 10 шагов назад. Со временем я постепенно понял, почему функциональное программирование именно на Clojure — это здорово, и почему я не сделал 10 шагов назад. Вот мои любимые вещи из Clojure…

Функции первого класса

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

В Clojure этого можно добиться, используя такие функции первого класса:

неизменность

Я считаю, что изменяемое или глобальное состояние добавляет сложности любому языку. Вот почему мне нравится Clojure. По умолчанию в Clojure все неизменяемо. Все локальные переменные неизменяемы. Все функции чистые (что означает отсутствие побочных эффектов). Наличие побочных эффектов означает, что вам нужно беспокоиться о том, откуда они вызываются и как они влияют на вашу программу, что приведет к пустой трате времени. Вот почему мне нравится Clojure, у него практически нет побочных эффектов. Когда я запускаю функцию, я точно знаю, для чего она предназначена и что именно произойдет. Я передаю функции аргументы, она что-то с ними делает и возвращает результат. Функция вернет точный некоторый результат с точно такими же аргументами. Это чистая функция.

Это значительно упрощает отладку, рефакторинг, тестирование и работу с кодовой базой в целом.

Работа с данными

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

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

for (int i = 0; i < 10; i++)
{
...
}

Мы понятия не имеем, что будет делать этот цикл, пока не прочитаем тело. Он может суммировать значения в массиве. Он может найти наибольшее значение в массиве. Каждый из этих шаблонов является идиоматической функцией в Clojure (карта, фильтр, уменьшение, максимум). Это заставляет ваш код показывать свои настоящие намерения и облегчает чтение. Идиоматические функции для работы со структурами данных не уникальны для Clojure, но они по-прежнему являются важным фактором, благодаря которому мне нравится этот язык.