Скрытые возможности Clojure
Какие менее известные, но полезные функции Clojure вы используете? Не стесняйтесь делиться небольшими хитростями и идиомами, но постарайтесь ограничить себя Core и Contrib.
Я нашел действительно интересную информацию в ответах на подобные вопросы:
- Скрытые возможности Haskell
- Скрытые возможности Python
- Скрытые возможности Java
- Скрытые возможности C
- Скрытые возможности Perl
- Скрытые возможности Ruby
Есть еще много вопросов о "скрытых возможностях" для других языков, поэтому я подумал, что было бы неплохо иметь такой же вопрос для Clojure.
5 ответов
Clojure имеет неизменяемый тип данных постоянных очередей PersistentQueue, но у него (пока?) Нет синтаксиса литерального чтения или функций-обёрток Clojure, поэтому вам нужно создать его с помощью вызова Java. Очереди направляются (толкают) в заднюю часть и выдвигаются спереди с хорошей производительностью.
user> (-> (clojure.lang.PersistentQueue/EMPTY)
(conj 1 2 3)
pop)
(2 3)
Списки соединяются вперед и выскочить спереди. Векторы направляются назад и выскочить сзади. Таким образом, очереди иногда именно то, что вам нужно.
user> (-> ()
(conj 1 2 3)
pop)
(2 1)
user> (-> []
(conj 1 2 3)
pop)
[1 2]
(defn foo [a & [b c]] ...)
Вы можете деструктурировать остальные аргументы.
Обновить:
Последняя фиксация git-репо (29389970bcd41998359681d9a4a20ee391a1e07c) позволила выполнить ассоциативную деструктуризацию следующим образом:
(defn foo [a & {b :b c :c}] ...)
Очевидное использование этого для аргументов ключевого слова. Обратите внимание, что этот подход не позволяет смешивать аргументы ключевых слов с аргументами остальных (не то, что это может понадобиться очень часто).
(defn foo [a & {:keys [b c] :or {b "val1" c "val2"}] ...)
Если вы хотите значения по умолчанию для ключевых слов аргументов.
Прочитанный макрос читателя: #=
(read-string "#=(println \"hello\")")
Этот макрос может представлять угрозу безопасности, если read
используется при вводе данных пользователем (что само по себе является плохой идеей). Вы можете отключить этот макрос, установив *read-eval*
в false
,
Вы можете apply
функции в бесконечные аргументы последовательности. Например
(apply concat (repeat '(1 2 3)))
производит ленивую последовательность 1,2,3,1,2,3... Конечно, чтобы это работало, функция также должна быть ленивой по отношению к списку аргументов.
От все более и более хорошего сайта ClojureDocs идиома, использующая juxt
http://clojuredocs.org/clojure_core/clojure.core/juxt
;juxt is useful for forking result data to multiple termination functions
(->> "some text to print and save to a file"
((juxt
println
(partial spit "useful information.txt"))))