Скрытые функции Clojure

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

Я нашел очень интересную информацию в ответах на эти похожие вопросы:

Есть много вопросов "Скрытая функция" для других языков, поэтому я подумал, что было бы неплохо иметь один для Clojure тоже.

Ответ 1

Clojure имеет неизменный, постоянный тип данных очереди, PersistentQueue, но он еще не имеет литературного синтаксиса или Clojure обертки, поэтому вам нужно создать его через Java-вызов. Queues conj (push) на задней панели и поп с фронта с хорошей производительностью.

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]

Ответ 2

(defn foo [a & [b c]] ...)

Вы можете разрушить аргумент rest.

Update:

Последняя фиксация в git repo (29389970bcd41998359681d9a4a20ee391a1e07c) позволила выполнить ассоциативное деструктурирование следующим образом:

(defn foo [a & {b :b c :c}] ...)

Очевидное использование этого - для аргументов ключевого слова. Обратите внимание, что этот подход не позволяет смешивать аргументы ключевого слова с аргументами отдыха (не для того, чтобы что-то очень часто нужно было).

(defn foo [a & {:keys [b c] :or {b "val1" c "val2"}] ...)

Если вам нужны значения по умолчанию для аргументов ключевого слова.

Ответ 3

Макрос чтения чтения: #=

(read-string "#=(println \"hello\")")

Этот макрос может представлять угрозу безопасности, если read используется для ввода пользователем (что, пожалуй, является плохой идеей). Вы можете отключить этот макрос, установив *read-eval* в false.

Ответ 4

Вы можете apply использовать бесконечные последовательности аргументов. Например

(apply concat (repeat '(1 2 3)))

создает ленивую последовательность 1,2,3,1,2,3... Конечно, для этого для работы функция также должна быть ленивой относительно своего списка аргументов.

Ответ 5

Из все более и более хорошего сайта 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"))))