2011-01-19 7 views
15

Ho pensato che lo avrebbe fatto use ma sembra che la mappatura creata nello spazio dei nomi corrente non sia pubblica. Ecco un esempio di quello che vorrei realizzare:Posso riferire un altro spazio dei nomi ed esporre le sue funzioni come pubbliche per gli attuali ns?

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

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

Poi ho un altro spazio dei nomi in questo modo:

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

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

Vorrei farlo perché another-ns è una libreria per accedere a un database . Vorrei isolare tutte le chiamate a questa libreria in un singolo spazio dei nomi (my-ns), in questo modo tutte le funzioni dipendenti dal DB sarebbero isolate in un singolo spazio dei nomi e diventa più semplice passare a un altro DB se necessario.

Alcune delle funzioni di questa libreria vanno bene per me, ma mi piacerebbe aumentare le altre. Diciamo che le funzioni di lettura vanno bene, ma mi piacerebbe aumentare le funzioni di scrittura con alcune convalide.

L'unico modo che vedo finora è quello di codificare manualmente tutti i mapping in my-ns anche per le funzioni che non riesco ad aumentare.

risposta

8

fa questo aiuto?

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

Ecco un esempio:

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

Se si vuole tirare solo in ogni cosa, allora:

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

(pullall clojure.string) 
+0

Ben fatto! Ho cambiato il tuo marchio di accettazione. Grazie. – Damien

+0

Hmm. Utile, ma sembra essere limitato agli spazi dei nomi che contengono solo le funzioni: 'Impossibile prendere il valore di una macro'. –

11

Un modo per farlo in modo selettivo (specificando esplicitamente ciascuna funzione) è utilizzare qualcosa come Zach Tellman Potemkin library. Un esempio del suo utilizzo si trova nello spazio dei nomi lamina.core che funge da punto di accesso pubblico per Lamina, importando le funzioni pubbliche chiave da tutti gli altri spazi dei nomi interni.

È inoltre possibile utilizzare clojure.contrib.def/defalias:

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

Molto utile, grazie mille. – Damien

+5

Potemkin è fantastico. Ho trovato questo più utile rispetto alla risposta accettata, che non funziona su macro. –

+0

'defalias' era [non proprio un alias ma una copia] (https://groups.google.com/d/msg/clojure/LhidPSlvX_Q/mS4R_52suXwJ) – beluchin

1

a tirare di tutto, dai nomi che possono avere le macro definite all'interno uso questo

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