Скрытые возможности Clojure

Какие менее известные, но полезные функции Clojure вы используете? Не стесняйтесь делиться небольшими хитростями и идиомами, но постарайтесь ограничить себя Core и Contrib.

Я нашел действительно интересную информацию в ответах на подобные вопросы:

Есть еще много вопросов о "скрытых возможностях" для других языков, поэтому я подумал, что было бы неплохо иметь такой же вопрос для 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"))))

Другие вопросы по тегам