2012-04-23 13 views
6

estoy frente a un problema en la forma de la arquitectura de una determinada pieza de mi software. que permite decir, tengo una función llamada make-temp-dir (y muchos otros) que hace un poco de magia oscuro, dependiendo del sistema operativo actual. Quiero ser capaz de poner las implementaciones de estos métodos para cada sistema operativo en un espacio de nombres separado.despacho dependientes Medio Ambiente de protocolos/métodos múltiples en clojure

En primer lugar, creo que los protocolos (si es posible) o los multimétodos son la solución a esto. Sin embargo, nunca he visto un ejemplo de uso de estos con las implementaciones que abarca varios espacios de nombres. Y no puedo imaginar cómo funcionaría esto .

En segundo lugar, si uso protocolos para esto, voy a tener que llamar a los métodos algo como

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

De alguna manera, pasando por el sistema operativo como primer argumento todo el tiempo no parece demasiado buena a mi. Por motivos semánticos, me gustaría que el make-temp-dir tome decisiones inteligentes dependiendo del sistema operativo. Claro que puedo usar algunas macros y hacer algo como

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

pero eso se siente mal.

¿Cómo se debe hacer esto? ¿O estoy yendo por el camino equivocado? Cualquier ayuda apreciada.

Editar: De acuerdo, muchas gracias a @kotarak, logré que algo funcione. Para cualquiera que tropiece con esto, https://gist.github.com/2477120. Está funcionando bien, creo que voy a ir con eso. Gracias a todos.

Respuesta

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] 
    (...)) 

En su código de inicio que tienen que inicializar current-os con alter-var-root antes de usar cualquiera de las funciones de utilidad.

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

Espero que empieces.

+0

Por lo tanto, la segunda pieza de código es necesario que haya en 'derecho your.utils' espacio de nombres? Además, ¿cuál es el macro del lector '# ''? Disculpe, tampoco sé cómo googlearlo;) –

+0

'#'' se llama * cotización * var. Puede encontrar una descripción de las cotizaciones var en https://groups.google.com/forum/?fromgroups#!topic/clojure/jDBAJD4nWqs. – user100464

+0

@kotarak, bien, solución increíble. Me tomó tanto tiempo digerirlo, pero creo que entiendo lo que está pasando. Sin embargo, me gustaría recibir algunas opiniones sobre mi primer comentario. –

1

No puedo decir con certeza, pero parece que usted puede terminar encima de reinventar la rueda que Java le proporciona. Pruebe https://github.com/Raynes/fs para un envoltorio conveniente en algunos de lo que Java proporciona más allá de las herramientas básicas en clojure.java.io (http://clojuredocs.org/clojure_core/clojure.java.io).

Usted puede encontrar también https://github.com/drakerlabs/milieu útil si su pregunta se extienden más allá el sistema operativo específico de ramificación a los valores de configuración específicos del entorno. Escribí este código como parte de nuestros proyectos patentados aquí en Draker, y recientemente lo lanzamos como software libre. Todavía no lo hemos anunciado oficialmente a la comunidad, pero está en Clojars y listo para usar. Comentarios son apreciados! El concepto que impulsó su creación fueron los entornos en el sentido de desarrollo/prueba/puesta en escena/producción, etc., pero no veo ninguna razón por la cual no podría usarse para configurar variables para diferentes entornos de SO también.

+1

Gracias por los enlaces rplevy. Creo que el paquete fs será útil para mí :) –

Cuestiones relacionadas