我很可能会以错误的方式处理此问题,因此请原谅我的天真:
为了学习Clojure,我已经开始将Python的OAuth客户端库移植到Clojure。我这样做的方式与我在Python库中包装Python请求的方式相同,将clj-http进行包装。到目前为止,这似乎运行良好,我真的很高兴看到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之间是完全相同的。我的第一个 react 是将这些函数移入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
未找到var
oauth2/get
,因为仅将其拉到oauth2.clj的 namespace 中似乎并没有将其公开,就好像它实际上在该 namespace 中一样。我不想用更多的功能包装它们,因为这基本上违背了目的。这些函数是如此简单(它们只是包装了一个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中做到这一点,或者应该习惯于提供这种DRY抽象呢?
最佳答案
考虑看看Zach Tellman的库Potemkin。 Zach将其描述为“用于重组 namespace 和代码结构的功能集合”。
Potemkin并非没有争议。 Here's Clojure邮件列表上一个话题的开始,Stuart Sierra清楚地表明他不喜欢这个想法。
关于function - 在Clojure中的命名空间之间共享功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15580807/