2008-10-17 4 views

Répondre

31

Voici une fonction make-keyword qui empaquette le processus de création de mot-clé (intern d'un nom dans le paquet KEYWORD). :-)

(defun make-keyword (name) (values (intern name "KEYWORD"))) 
+0

Presque, mais pas tout à fait. Lorsque vous créez un mot-clé, vous devez également vous assurer que vous définissez sa liaison de valeur sur lui-même. – Vatine

+0

@Vatine Je n'ai que SBCL à tester, et dans SBCL, '(valeur-symbole (intern" FOO "" KEYWORD "))' a déjà la valeur correcte. En outre, Alexandrie l'implémente en utilisant la même approche également. –

+9

@Vatine [11.1.2.3.1 Internation d'un symbole dans le package KEYWORD] (http://www.lispworks.com/documentation/HyperSpec/Body/11_abca.htm) dit (soulignement ajouté), * "Le package KEYWORD est traité différemment des autres paquets en ce sens que des actions spéciales sont effectuées lorsqu'un symbole y est interné.En particulier, lorsqu'un symbole est interné dans le package KEYWORD, il est automatiquement fait pour être un symbole externe et ** est automatiquement fait pour être un variable constante avec lui-même comme une valeur. ** "* –

-5
(intern "foo" "KEYWORD") -> :foo 

Voir la Strings section du Common Lisp Cookbook pour d'autres conversions chaîne/symbole et une analyse détaillée des symboles et des paquets.

+3

Le nom doit être interné dans le paquet « KEYWORD » être un mot-clé. par exemple, (stagiaire "FOO" "KEYWORD") –

+0

ah oui. Le (stagiaire "foo" "KEYWORD") fonctionne assez bien. Je vous remercie. – nathan

+0

Dans ma réponse, je l'ai emballé dans une petite fonction soignée, que vous pouvez apprécier. :-) –

35

Les réponses données à peu près correctes ne produisent pas une solution correcte à l'exemple de la question.

Tenir compte:

CL-USER(4): (intern "foo" :keyword) 

:|foo| 
NIL 
CL-USER(5): (eq * :foo) 

NIL 

Habituellement vous souhaitez appliquer STRING-UPCASE à la chaîne avant interner il, ainsi:

(defun make-keyword (name) (values (intern (string-upcase name) "KEYWORD"))) 
+1

Il se peut, bien sûr, que OP ait juste un print-case défini sur': downcase' ... –

2

Il y a une fonction make-keyword dans la bibliothèque Alexandria, bien qu'il Conservez le cas afin d'obtenir exactement ce que vous voulez, vous devrez d'abord monter la ficelle.

+0

Ou alors, définissez 'print-case' à': downcase'. 'intern' ne fait aucune modification de cas, donc la solution ici ne devrait probablement pas non plus. (Bien que l'exemple dans la question dise '(mot-clé" foo ") =>: foo', il est probablement préférable d'avoir' (... "foo") =>: | foo | 'ou' (... " FOO ") =>: FOO'.) –

1

Dans cet exemple, il traite aussi des cordes avec des espaces (en les remplaçant par des points):

(defun make-keyword (name) (values (intern (substitute #\. #\space (string-upcase name)) :keyword))) 
+1

Y a-t-il une raison pour laquelle vous voudriez remplacer les espaces par des points? Si vous faites un '' foo bar '', vous obtenez un symbole avec le nom' 'foo bar'', et il n'y a pas de problème avec ça. 'intern' ne remplace pas les espaces avec des points. –