2012-04-23 12 views
6

sto di fronte a un problema nel modo in cui all'architettura un particolare pezzo di mio software. consente di dire, ho una funzione chiamata make-temp-dir (e molti altri) che fa qualche magia scuro a seconda del sistema operativo corrente. Voglio essere in grado di mettere le implementazioni di questi metodi per ogni sistema operativo in uno spazio dei nomi separato.Ambiente spedizione dipendente di protocolli/multimethods in clojure

In primo luogo, ritengo che i protocolli (se possibile) o multimetodi siano la soluzione a . Tuttavia, non ho mai visto un esempio di utilizzo di queste con le implementazioni che si estendono su più domini. E non sono in grado di capire come funzionerebbe questo out.

In secondo luogo, se uso di protocolli per questo, dovrò chiamare i metodi qualcosa di simile

(make-temp-dir current-os arg-1 arg-2) 

In qualche modo, passando il sistema operativo come primo argomento per tutto il tempo non sembra troppo buono per me. Per amor semantico, mi piacerebbe che il make-temp-dir prendere decisioni intelligenti a seconda del sistema operativo. Certo posso usare alcune macro e fare qualcosa di simile

(doto current-os 
    (make-temp-dir arg-1 arg2)) 

ma che si sente male.

Come dovrebbe essere fatto? O sto andando nella direzione sbagliata? Qualsiasi aiuto apprezzato.

Modifica: Ok, grazie a @kotarak, sono riuscito a far funzionare qualcosa. Per chiunque inciampi su questo, https://gist.github.com/2477120. Funziona bene, penso che andrò con quello. Grazie a tutti.

risposta

7
(ns your.utils) 

(def current-os) 

(defmulti make-temp-dir 
    (fn [& _] current-os)) 

(ns your.utils.mac) 

(defmethod make-temp-dir :mac-os-x 
    [a b] 
    (...)) 

(ns your.utils.win) 

(defmethod make-temp-dir :windows 
    [a b] 
    (...)) 

Nel codice di avvio è necessario inizializzare current-os con alter-var-root prima di utilizzare una qualsiasi delle funzioni di utilità.

(let [os (find-os)] 
    (alter-var-root #'current-os (constantly os)) 
    (require (case os 
      :mac-os-x 'your.utils.mac 
      :windows 'your.utils.win))) 

Spero che tu possa iniziare.

+0

Quindi, il secondo pezzo di codice deve essere in 'giusto spazio dei nomi your.utils'? Inoltre, qual è la macro del lettore '# '- scusate, non so come google che sia;) –

+0

' #' 'è chiamato un * var quote *. Puoi trovare una descrizione delle virgolette su https://groups.google.com/forum/?fromgroups#!topic/clojure/jDBAJD4nWqs. – user100464

+0

@kotarak, Ok, soluzione eccezionale. Mi ci è voluto tanto tempo per digerirlo, ma penso di capire cosa sta succedendo. Mi piacerebbe comunque qualche input sul mio primo commento. –

1

Non posso dire per certo, ma suona come si può finire per reinventare una ruota che Java offre. Prova https://github.com/Raynes/fs per una vantaggiosa involucro su alcune delle cose che Java fornisce al di là gli strumenti fondamentali in clojure.java.io (http://clojuredocs.org/clojure_core/clojure.java.io).

Si possono trovare anche https://github.com/drakerlabs/milieu utile se la domanda si estendono al di là di ramificazione OS-specifica per valori di configurazione specifici dell'ambiente. Ho scritto questo codice come parte dei nostri progetti proprietari qui a Draker e recentemente lo abbiamo rilasciato come software libero. Non l'abbiamo ancora annunciato ufficialmente alla comunità, ma è in Clojars e pronto per l'uso. Il feedback è apprezzato! Il concetto che ha guidato la sua creazione era l'ambiente nel senso di dev/test/staging/produzione, ecc., Ma non vedo ragioni per cui non possa essere usato per configurare le variabili anche per diversi ambienti OS.

+1

Grazie per il link rplevy. Penso che il pacchetto fs mi tornerà utile :) –