В проект clj-http приняли мой скромный пулл-реквест. Теперь, если запрос был вызван с флагом :throw-exceptions true и вернулся плохой ответ (статус не 2хх, 3хх), то во вбрасываемый словарь добавляеся ключ :type :clj-http.client/unexceptional-status. Это на ура работает с библиотекой Slingshot, потому что отлов исключений по полю :type стал негласным стандартом.

Если абзац выше звучит для вас бессмыслецей, расскажу подробней. Изначально в Кложе идут унылые Java-исключения, которые плохо ложаться на мир структур и коллекций. Но поскольку Кложа это Лисп, а в Лиспе любая проблема решается его же силами, умельцы написали библиотеку для альтернативных исключений slingshot.

Библиотека упрощает работу с исключениями до мыслимого предела. Теперь можно вбрасывать не только объект, унаследованный от Throwable, а вообще что угодно. Лучше всего подходит словарь. Форма отлова исключения, выброшенного из slingshot, может иметь разную структуру. Например, предикат, но удобней и короче будет вектор двух элементов, где первый – ключ, а второй – значение.

Если раньше приходилось передавать неочевидный предикат, который проверял, что в словаре есть поле status, и оно числовое:

(catch
  (fn [response]
    (-> response :statsus integer?))
  ...)

, то теперь достаточно сравнить так:

(catch [:type :clj-http.client/unexceptional-status])

Визуально разницы мало, но селектор по ключу :type открывает новые горизонты. Например, во врейморке Compojure API, на котором наш проект, обработка исключений целиком работает на этом принципе. В особом словаре лежат ключи – потенциальные варианты :type, а значения – функции-обработчики. Хорошие примеры в документации.

Пока пулл-реквест не приняли, приходилось писать свой костыль для добавления ключа. Теперь с этим покончено.