ich das sehr gut in der falschen Art und Weise nähern kann, so bitte ich meine Naivität vergeben:-Sharing-Funktionen zwischen Namespaces in Clojure
Um Clojure zu lernen, die ich für Python meine OAuth-Client-Bibliothek begonnen habe Portierung auf Clojure. Ich mache das, indem ich clj-http auf die gleiche Weise umschlinge, wie ich Python-Anfragen in die Python-Bibliothek einpacke. Das scheint bisher ziemlich gut zu funktionieren und ich genieße es wirklich, die Umsetzung in Clojure lebendig werden zu sehen.
Ich bin jedoch auf ein Problem gestoßen: Ich habe vor, sowohl OAuth 1.0 und 2.0 zu unterstützen, als auch die entsprechenden Funktionen in zwei Dateien zu teilen: oauth1.clj und oauth2.clj. Nun sollte jede Datei idealerweise eine Reihe von Funktionen verfügbar machen, die HTTP-Verben entsprechen.
(ns accord.oauth2)
...
(defn get
[serv uri & [req]]
((:request serv) serv (merge req {:method :get :url uri})))
Diese Funktionen werden im Wesentlichen identisch sein und in der Tat sind jetzt völlig identisch zwischen oauth1.clj und oauth2.clj. Meine erste Reaktion war, diese Funktionen in core.clj zu verschieben und sie dann in den entsprechenden OAuth-Namespaces (oauth1, oauth2) zu verlangen, um zu vermeiden, dass derselbe Code zweimal geschrieben wird.
Das ist in Ordnung, solange ich die verwiesenen Funktionen in der Datei verwende, d. H. Oauth1.clj oder oauth2.clj. Aber lassen Sie uns sagen, dass wir diese Bibliothek verwenden möchten, wie ich (hier in der REPL alternativ Ihr Programm) bin zu wollen, so etwas wie dieses:
=> (require '[accord.oauth2 :as oauth2]) ;; require the library's oauth2 namespace
...
=> (oauth2/get my-service "http://example.com/endpoint") ;; use the HTTP functions
Der var oauth2/get
nicht gefunden wird, weil es in den Namensraum in oauth2 ziehen .clj allein scheint es nicht zu entlarven, als wäre es tatsächlich in diesem Namensraum. Ich möchte sie nicht mit mehr Funktionen umhüllen, weil das im Grunde den Zweck verfehlt; Die Funktionen sind so einfach (sie wickeln nur eine request
Funktion) Ich würde sie an drei Stellen schreiben, im Wesentlichen, wenn ich das tun würde.
Ich bin sicher, ich bin nicht Nekromanten in Clojure richtig grokking und darüber hinaus vielleicht die allgemeine Art des Denkens über Abstraktion Probleme und Code-Sharing idiomatisch.
Also ich frage mich, was die idiomatische Lösung dafür ist? Gehe ich das völlig falsch?
Edit:
Hier ist eine Vereinfachung des Problems: https://gist.github.com/maxcountryman/5228259
Beachten Sie, dass das das Ziel ist, die HTTP-Verb funktioniert eine Zeit zu schreiben. Sie brauchen keine speziellen Versandarten oder so etwas. Sie sind schon in Ordnung, wie sie sind. Das Problem ist, dass sie nicht von accord.oauth1
oder accord.oauth2
ausgesetzt sind, d. H. Wenn Ihr Programm zum Beispiel accord.oauth2
erfordert.
Wenn diese Python waren, konnten wir importieren nur die Funktionen wie folgt aus: from accord.core import get, post, put, ...
in accord.oauth1
und accord.oauth2
und dann, wenn wir das accord.oauth1
Modul verwendet würden wir Zugriff auf alle diese importierten Funktionen haben, zum Beispiel import accord.oauth2 as oauth2
... oauth2.get(...)
.
Wie können wir das in Clojure tun oder wie sollten wir idiomatisch für diese Art von DRY Abstraktion sorgen?
"Meine erste Reaktion war, diese Funktionen in core.clj zu verschieben und sie dann in den entsprechenden OAuth-Namespaces (oauth1, oauth2) zu verlangen, um zu vermeiden, denselben Code zweimal zu schreiben." Hast du das gemacht? Wenn ja, warum müssen Sie es im zweiten Codeblock anfordern? In welcher Datei/welchem Namespace befindet sich dieser zweite Codeblock? –
Bitte geben Sie den spezifischen Compilerfehler an. – noahlz
@tieTY Ich habe die HTTP-Verb-Funktionen in core.clj verschoben, was der Namensraum 'accord.core' ist. Dann benötigen die Namensräume 'accord.oauth1' und' accord.oauth2' diese Funktionen, indem sie: alle aus 'accord.core' in ihre jeweiligen Namespaces verweisen. Das Problem dabei ist, dass Sie 'accord.oauth2' nicht benötigen können, sagen Sie in der REPL oder von Ihrem Programm, und verwenden Sie dann die HTTP-Funktionen auf diese Weise:' accord.oauth2/get'. Wenn die Funktionen tatsächlich zweimal in jeder Datei geschrieben würden, würde das funktionieren. Ich versuche das jedoch zu vermeiden. :) – maxcountryman