2010-09-21 13 views
9

Dans Clojure, comment obtenir le nom de l'espace de noms dans lequel les variables et les fonctions sont nommées? Par exemple, l'amélioration de ce qui suit:Clojure: référence au nom de l'espace de noms

(ns my-ns) 

(def namespace-name "my-ns") 

Le problème avec ce qui précède est que si je veux changer le nom de mes-ns, je dois changer la définition du nom espace de noms et

Répondre

11

Une simple modification de la réponse d'Arthur fonctionne bien.

(def namespace-name (ns-name *ns*)) 

Cependant, je veux mettre en garde les débutants Clojure que

(defn namespace-name [] (ns-name *ns*)) 

ne fonctionnera pas pour les fins de cette question, puisque * ns * est lié dynamiquement.

+2

Mais quelque chose le long de la ligne (defmacro defns-name [nom] '(def ~ name (ns-name * ns *))), puis call (nom-espace-noms-defns) fonctionnerait. –

+0

Markdown a mangé les étoiles autour de 'ns' dans le commentaire de Nicolas ci-dessus: devrait se lire:' (defmacro defns-name [nom] \ '(def ~ nom (ns-name * ns *)))'. –

6

la espace de nommage est stocké dans

*ns* 

depuis votre fonction est évaluée lors de l'exécution, vous obtenez ce que jamais cette valeur de * ns * est lorsque vous l'appelez. Par conséquent, si vous souhaitez en conserver une copie, vous pouvez utiliser le

.

+0

Voulez-vous dire (définition namespace-name (ns nom \ * ns \ *))? – chris

+0

Je tape * ns * et apparaît en italique? comment j'écris cela si SO l'a affiché littéralement? –

+0

ahh il l'a fait encore! * ns * –

3

pour créer et stocker un espace de noms, vous pouvez faire:

user=> (def working-namespace (create-ns 'my-namespace)) 
#'user/working-namespace 

user=> working-namespace 
#<Namespace my-namespace> 

user=> (class working-namespace) 
clojure.lang.Namespace 

vous venez de recevoir un objet Namespace, mais je ne peux pas vous dire beaucoup sur ce que vous pouvez faire. Jusqu'à présent, je ne connais que de la fonction stagiaire des thats acceptent un objet Namespace

user=> (intern working-namespace 'my-var "somevalue") 
#'my-namespace/my-var 
1

ok, avec l'aide de ce gars-là, Michael Kohl, je l'ai trouvé comment passer à un espace de noms tenu dans une variable (read here for more details)

donc, on y va:

user=> (def working-namespace (create-ns 'my-namespace)) 
#'user/working-namespace 
user=> (in-ns (symbol (str working-namespace))) 
#<Namespace my-namespace> 
my-namespace=> 
;; notice how it switched to "my-namespace" 

;; now if i were to put some other namespace in that variable... 
my-namespace=> (ns user) 
nil 
user=> (def working-namespace (create-ns 'other-namespace)) 
#'user/working-namespace 

;; and switch again, i would get the new namespace 
user=> (in-ns (symbol (str working-namespace))) 
#<Namespace other-namespace> 
other-namespace=> ; tadaa! 

bien que je ne pense pas qu'il est idiomatiques clojure de réattribuer les variables, vous pourriez construire cela en une fonction qui obtient le support var pour namespace en tant que paramètre

maintenant pour obtenir la valeur d'un var intérieur et à l'extérieur que l'espace de noms

user=> (intern working-namespace 'some-var "my value") 
#'other-namespace/some-var 

user=> (var-get (intern working-namespace 'some-var)) 
"my value"