Clojure
Clojure | |
---|---|
![]() | |
Класс языка | функциональный, мультипарадигмальный |
Появился в | 2007 |
Автор | Рич Хикки |
Разработчик | Ричард Хикки |
Расширение файлов |
.clj , .cljs , .cljc , .edn или .cljr |
Выпуск | |
Система типов | динамическая, строгая |
Испытал влияние | Lisp, ML, Haskell, Erlang[2], Prolog, Scheme, Java, Ruby[3] |
Повлиял на | Elixir |
Лицензия | Eclipse Public License |
Сайт | clojure.org |
![]() |
Clojure (произносится как closure [ˈklōZHər]) — современный диалект Лиспа, язык программирования общего назначения с поддержкой разработки в интерактивном режиме, поощряющий функциональное программирование и упрощающий поддержку многопоточности. Clojure работает на платформах JVM и CLR. Clojure отличает философия «код как данные» (гомоиконность) и развитая система лисп-макросов.
Транслятор Clojure свободно распространяется на условиях Eclipse Public License.
Философия
[править | править код]Рич Хикки разработал Clojure как современный Лисп для функционального программирования с интеграцией в Java-платформу, спроектированный для поддержки параллелизма.[4]
Синтаксис
[править | править код]Как и в любом другом Лиспе, синтаксис Clojure основан на S-выражениях, которые перед компиляцией транслируются синтаксическим анализатором в структуры данных. Синтаксический анализатор Clojure поддерживает, помимо обычных списков, синтаксис литералов для ассоциативных массивов, множеств и векторов, передавая затем все эти структуры данных компилятору. Иначе говоря, компилятор Clojure компилирует не только списковые структуры данных, но и напрямую поддерживает все указанные типы.
Хотя Clojure является расширением изначальной версии Lisp, он не совместим с Lisp’ом, то есть программа на любой из современных версий Lisp’а (за исключением, возможно, самых коротких, примитивных и, к тому же, специально подобранных примеров) либо вообще не пройдёт транслятор Clojure, либо будет выполняться неправильно. Отличия от распространённых версий Lisp’а приведены на сайте языка[5]. Вот некоторые из них:
- идентификаторы регистро-зависимы;
- оригинальный синтаксис для литералов, векторов, отображений (maps), регулярных выражений, анонимных функций и ряда других синтаксических элементов;
- утрачена многозначность значения nil (которое в Lisp обозначает и пустой указатель, и пустой список, и логическое значение «ложь») — оно означает только отсутствующее значение (пустую ссылку, подобно null в Java), для прочих значений используется специфический синтаксис;
- многие традиционные функции поменяли имена, например, car и cdr заменены на first и rest;
- поддерживаются одноимённые функции с различными наборами аргументов;
- отсутствуют макросы чтения (read macros), что лишает возможности изменять синтаксис языка;
- часть оставшихся неизменными синтаксических элементов изменили смысл;
- появилась поддержка «ленивых» коллекций.
Макросы
[править | править код]Макросистема Clojure очень похожа на аналогичную систему Common Lisp, за двумя исключениями:
- При раскрытии форм под знаком обратной кавычки
`
(англ. back quote), который в Clojure именуется термином «syntax-quote», происходит автоматическая явная квалификация каждого символа тем пространством имён, к которому он относится в точке определения макроса. Такой порядок исключает непреднамеренное связывание с одноимённым символом из «чужого» пространства имён при раскрытии макроса. Сослаться в макросе на символ из другого пространства имён возможно, но только путём его явной квалификации. - Для выделения промежуточных вычислений под знаком обратной кавычки вместо
,
и,@
используются~
и~@
соответственно.
Особенности языка
[править | править код]- Динамическая, интерактивная разработка в REPL-цикле
- Функции как объекты первого класса с акцентом на рекурсию, а не на основанную на побочных эффектах итерацию
- «Ленивые» последовательности
- Обеспечивает богатый набор неизменяемых, сохраняемых структур данных[англ.]
- Параллельное программирование с поддержкой транзакционной памяти, агентной системы и системы динамических переменных
- Clojure — компилируемый язык, результатом компиляции является байткод JVM
- Тесная интеграция с Java: за счёт компиляции в байткод JVM программы на Clojure легко переносятся в любую среду с JVM. Язык также обеспечивает ряд макросов, которые упрощают использование в нём существующих Java API. Структуры данных Clojure реализуют все стандартные интерфейсы Java, что делает легким запуск из Java программного кода написанного на Clojure.
Примеры
[править | править код](println "Привет, мир!")
Потокобезопасный генератор уникальных серийных номеров:
(let [i (atom 0)]
(defn generate-unique-id
"Возвращает различные числовые ID для каждого вызова."
[]
(swap! i inc)))
Анонимный подкласс java.io.Writer
который ничего не выводит и макрос, используемый чтобы заглушить весь вывод внутри него:
(def bit-bucket-writer
(proxy [java.io.Writer] []
(write [buf] nil)
(close [] nil)
(flush [] nil)))
(defmacro noprint
"Вычисляет заданные выражения, заглушая весь *вывод* на экран".
[& forms]
`(binding [*out* bit-bucket-writer]
~@forms))
(noprint
(println "Hello, nobody!"))
10 потоков, манипулирующих одной общей структурой данных, которая состоит из 100 векторов, каждый из которых содержит 10 (изначально последовательных) уникальных чисел. Каждый поток многократно выбирает две случайных позиции в двух случайных векторах и обменивает местами их значения. Все изменения векторов происходят в единой транзакции путём использования системы транзакционной памяти clojure. Поэтому даже после 1000 итераций в каждом из потоков числа не теряются.
(defn run [nvecs nitems nthreads niters]
(let [vec-refs (vec (map (comp ref vec)
(partition nitems (range (* nvecs nitems)))))
swap #(let [v1 (rand-int nvecs)
v2 (rand-int nvecs)
i1 (rand-int nitems)
i2 (rand-int nitems)]
(dosync
(let [temp (nth @(vec-refs v1) i1)]
(alter (vec-refs v1) assoc i1 (nth @(vec-refs v2) i2))
(alter (vec-refs v2) assoc i2 temp))))
report #(do
(prn (map deref vec-refs))
(println "Distinct:"
(count (distinct (apply concat (map deref vec-refs))))))]
(report)
(dorun (apply pcalls (repeat nthreads #(dotimes [_ niters] (swap)))))
(report)))
(run 100 10 10 100000)
Вывод предыдущего примера:
([0 1 2 3 4 5 6 7 8 9] [10 11 12 13 14 15 16 17 18 19] ...
[990 991 992 993 994 995 996 997 998 999])
Distinct: 1000
([382 318 466 963 619 22 21 273 45 596] [808 639 804 471 394 904 952 75 289 778] ...
[484 216 622 139 651 592 379 228 242 355])
Distinct: 1000
См. также
[править | править код]Примечания
[править | править код]- ↑ Release 1.11.4 — 2024.
- ↑ Rich Hickey. Books that influenced Clojure (30 июня 2009). Дата обращения: 11 сентября 2009. Архивировано из оригинала 18 апреля 2012 года.
- ↑ Clojure Programming . Дата обращения: 30 апреля 2013. Архивировано 21 мая 2015 года.
- ↑ Rationale . Rich Hickey. clojure.org. Дата обращения: 17 октября 2008. Архивировано из оригинала 18 апреля 2012 года.
- ↑ Различия между Clojure и Lisp . Дата обращения: 23 октября 2017. Архивировано 8 июля 2019 года.
Литература
[править | править код]- Halloway, Stuart (2009-05-28), Programming Clojure (1st ed.), Pragmatic Bookshelf, p. 304, ISBN 1934356336 Архивная копия от 12 февраля 2010 на Wayback Machine
- VanderHart, Luke (2010-06-07), Practical Clojure (1st ed.), Apress, p. 350, ISBN 1430272317, Архивировано из оригинала 17 сентября 2010, Дата обращения: 19 февраля 2010 Архивная копия от 17 сентября 2010 на Wayback Machine
- Rathore, Amit (Early 2011), Clojure in Action (1st ed.), Manning, p. 475, ISBN 9781935182597
{{citation}}
: Проверьте значение даты:|date=
(справка) - Fogus, Michael; Houser, Chris (December, 2010), The Joy of Clojure (1st ed.), Manning, p. 300, ISBN 9781935182641
{{citation}}
: Проверьте значение даты:|date=
(справка)
Ссылки
[править | править код]- официальный сайт Clojure (англ.)
- репозиторий кода Clojure на GitHub (англ.)
- Clojure — Functional Programming for the JVM (англ.) — подробный обзор языка
- Full Disclojure — Видеодемонстрация (англ.)
- На русском языке
- Язык программирования Clojure — Введение на IBM developerWorks
- Алекс Отт. Clojure, или «Вы все ещё используете Java? Тогда мы идем к вам!» в 4 выпуске журнала «Практика функционального программирования» (Обновленная версия статьи, с описанием версии 1.2)
- Форум о Clojure на lisper.ru
- ru_clojure — сообщество «Clojure» в «Живом Журнале»
- Русская планета Clojure — агрегатор русскоязычных блогов о Clojure