2011-01-19 6 views
15

Pensé que use lo haría, pero parece que el mapeo creado en el espacio de nombres actual no es público. Aquí está un ejemplo de lo que me gustaría lograr:¿Puedo referir otro espacio de nombres y exponer sus funciones como públicas para las ns actuales?

(ns my-ns 
    (:use [another-ns :only (another-fct)])) 

(defn my-fct 
    [] 
    (another-fct 123)) ; this works fine 

entonces tengo otro espacio de nombres como esto:

(ns my-ns-2 
    (:require [my-ns :as my])) 

(defn my-fct-2 
    [] 
    (my/another-fct 456)) ; this doesn't work 

me gustaría hacer eso porque another-ns es una biblioteca para acceder a una base de datos . Me gustaría aislar todas las llamadas a esta biblioteca en un solo espacio de nombres (my-ns), de esta manera todas las funciones dependientes de DB se aislarían en un solo espacio de nombres y será más fácil cambiar a otro DB si es necesario.

Algunas de las funciones de esta biblioteca son buenas para mí, pero me gustaría aumentar otras. Digamos que las funciones de lectura están bien, pero me gustaría aumentar las funciones de escritura con cierta validación.

La única forma que veo hasta ahora es codificar manualmente toda la asignación en my-ns incluso para las funciones que no aumenten.

Respuesta

8

¿Esto ayuda?

(defmacro pull [ns vlist] 
    `(do [email protected](for [i vlist] 
      `(def ~i ~(symbol (str ns "/" i)))))) 

He aquí un ejemplo:

(ns my-ns) 

(defmacro pull [ns vlist] 
    `(do [email protected](for [i vlist] 
      `(def ~i ~(symbol (str ns "/" i)))))) 

(pull clojure.string (reverse replace)) 

(defn my-reverse 
    [] 
    (reverse "abc")) 

(ns my-ns-2) 

(defn my-fct-2 [] 
    (list (my-ns/my-reverse) 
     (my-ns/reverse "abc"))) 

(my-fct-2) 

Si desea simplemente tire de todo, entonces:

(defmacro pullall [ns] 
    `(do [email protected](for [i (map first (ns-publics ns))] 
      `(def ~i ~(symbol (str ns "/" i)))))) 

(pullall clojure.string) 
+0

¡Bien hecho! Cambié la marca de aceptación para ti. Gracias. – Damien

+0

Hmm. Útil, pero parece estar limitado a los espacios de nombres que contienen funciones por sí solos: 'No se puede tomar el valor de una macro'. –

11

Una forma de hacer esto selectivamente (especificando cada función explícitamente) es usar algo como Zach Tellman's Potemkin library. Un ejemplo de su uso se encuentra en el espacio de nombres lamina.core que sirve como punto de entrada público para Lamina, importando las funciones públicas clave de todos los demás espacios de nombres internos.

También puede utilizar clojure.contrib.def/defalias:

(use 'clojure.contrib.def/defalias) 
(defalias foo clojure.string/blank?) 
(foo "") 
+0

Muy útil, muchas gracias. – Damien

+5

Potemkin es increíble. Encontré esto más útil que la respuesta aceptada, que no funciona en macros. –

+0

'defalias' era [no es realmente un alias sino una copia] (https://groups.google.com/d/msg/clojure/LhidPSlvX_Q/mS4R_52suXwJ) – beluchin

1

Para tirar de todo, desde el espacio de nombres que pueden tener las macros definidas dentro de utilización de este

(defmacro pullall [ns] 
    `(do [email protected](for [[sym var] (ns-publics ns)] 
      `(def ~sym ~var)))) 
Cuestiones relacionadas