2012-07-31 10 views
5

Tengo algunas funciones privadas en un espacio de nombres que me gustaría incluir en un segundo espacio de nombres. p.ej.Crear un alias a otro espacio de nombres Clojure

(ns one) 

(defn ^:private foo 
    "A docstring" 
    [x] (* x 2)) 

Y el segundo espacio de nombres tiene que crear un alias a esto:

(ns two) 

(def foo ???) 

(foo 3) ;; should work as if the function in namespace one was called 
=> 6 

Idealmente me gustaría preservar la cadena de documentación, así que no tengo que mantenerla en dos lugares. También me gustaría tener la opción de usar el mismo nombre o un nombre diferente.

El motivo de este requisito es el siguiente: la funcionalidad es necesaria/utilizada en el espacio de nombres one. one es una dependencia de two, y como no podemos tener dependencias circulares, no funcionará definir foo dentro de two. two es la API pública, por lo que foo debe formar parte pública del espacio de nombres two.

¿Cuál es la mejor manera de lograrlo?

+0

desea que el nombre de alias sea igual o puede ser cualquier cosa? – Ankur

+0

@Ankur: actualmente busca usar el mismo nombre, pero en algunos casos también podría ser útil crear un alias con un nombre diferente, por lo que sería genial si la solución lo permitiera. – mikera

+0

Prueba esto: '(def foo (with-meta one/foo (meta # 'one/foo))))' – Ankur

Respuesta

5

¿Qué tal esto:

(ns one) 

(defn- foo 
    "A docstring" 
    [x] (* x 2)) 

(ns two) 

(def foo-alias #'one/foo) 
(alter-meta! #'foo-alias merge (select-keys (meta #'one/foo) [:doc :arglists])) 

El truco está en no resolver el símbolo 'uno/foo, por lo tanto, evitando a desencadenar la bandera privada en sus metadatos. Luego, después del aliasing foo en tu segundo espacio de nombres, simplemente seleccionas los metadatos que deseas conservar de la definición anterior.

Cuestiones relacionadas