Совместное использование функций между пространствами имен в Clojure
Я вполне могу подойти к этому неправильно, поэтому, пожалуйста, прости меня за мою наивность:
Чтобы изучить Clojure, я начал переносить свою клиентскую библиотеку OAuth для Python на Clojure. Я делаю это, оборачивая clj-http так же, как оборачиваю запросы Python в библиотеку Python. Кажется, до сих пор это работает очень хорошо, и мне действительно нравится наблюдать за реализацией в Clojure.
Однако я столкнулся с проблемой: я планирую поддерживать OAuth 1.0 и 2.0 и разделить соответствующие функции на два файла: oauth1.clj и oauth2.clj. Теперь каждый файл в идеале должен предоставлять набор функций, которые соответствуют HTTP-глаголам.
(ns accord.oauth2)
...
(defn get
[serv uri & [req]]
((:request serv) serv (merge req {:method :get :url uri})))
Эти функции будут практически идентичны и фактически сейчас полностью идентичны между oauth1.clj и oauth2.clj. Моей первой реакцией было перенести эти функции в core.clj, а затем потребовать их в соответствующих пространствах имен OAuth (oauth1, oauth2), чтобы избежать написания одного и того же кода дважды.
Это нормально, если я использую упомянутые функции в файле, то есть oauth1.clj или oauth2.clj. Но допустим, что мы хотим использовать эту библиотеку, как я собираюсь (здесь, в REPL, в качестве альтернативы вашей программе), что-то вроде этого:
=> (require '[accord.oauth2 :as oauth2]) ;; require the library's oauth2 namespace
...
=> (oauth2/get my-service "http://example.com/endpoint") ;; use the HTTP functions
Варoauth2/get
не найден, потому что вытягивание его в пространство имен только в oauth2.clj, похоже, не раскрывает его так, как если бы оно было в этом пространстве имен Я не хочу оборачивать их большим количеством функций, потому что это в основном побеждает цель; функции так просты (они просто обернутьrequest
функция) Я бы написал их в трех местах, по сути, если бы я это сделал.
Я уверен, что не правильно понимаю пространства имен в Clojure и, более того, возможно, идиоматически думает о проблемах абстракции и совместном использовании кода.
Так что мне интересно, что это за идиоматическое решение? Я поступаю об этом совершенно неправильно?
Редактировать:
Вот упрощение проблемы:https://gist.github.com/maxcountryman/5228259
Обратите внимание, что цель состоит в том, чтобы написать функции глагола HTTP один раз. Им не нужны специальные типы отправки или что-то подобное. Они уже в порядке, как они. Проблема в том, что они не подвергаютсяaccord.oauth1
или жеaccord.oauth2
то есть когда ваша программа требуетaccord.oauth2
например.
Если бы это был Python, мы могли бы просто импортировать такие функции:from accord.core import get, post, put, ...
вaccord.oauth1
а такжеaccord.oauth2
а потом, когда мы использовалиaccord.oauth1
В модуле у нас будет доступ ко всем этим импортированным функциям, например,import accord.oauth2 as oauth2
...oauth2.get(...)
.
Как мы можем сделать это в Clojure или как идиоматически предусмотреть этот вид СУХОЙ абстракции?