Comment créer: des mots clés?

16

Q: Comment crée-t-on et utilise- :keywordst-on?

Envisagez une tentative (naïve, apparemment) d'accéder à la liste de jouets suivante:

(setf alist '((:key-1 "Key no. 1")
              (:key-2 "Key no. 2")))

(assq :key-1 alist)                 ; => (:key-1 "Key no. 1")
(assq (make-symbol ":key-1") alist) ; => nil

La première clé fonctionne comme prévu, mais pas la deuxième clé. Dans la mesure où il n'y a pas de make-keywordfonction évidente , comment créer et utiliser un mot-clé?

Motivation d'origine: j'ai besoin de transformer une chaîne en une clé de recherche qui est un symbole sur lequel je peux putpropriétés.

Dans le processus de formulation de cette question, j'ai obtenu au moins une partie de la réponse, que je poste séparément. J'espère que des esprits plus brillants que le mien pourront l'améliorer.

Dan
la source
1
(eq :foo (read ":foo"))
abo-abo

Réponses:

9

Vous avez raison de make-symbolcréer un mot-clé qui ne correspond eqà aucun mot-clé existant et internpourrait polluer l'obarray global avec le nouveau symbole. Entre ceux-ci, vous avez intern-soft, qui renvoie le symbole s'il a déjà été créé, ou nils'il n'a pas:

ELISP> (intern-soft ":key-1")
nil
ELISP> :key-1
:key-1
ELISP> (intern-soft ":key-1")
:key-1

Cela devrait convenir à votre objectif: si le mot-clé n'existe pas, il ne peut pas être présent dans la liste, il n'est donc pas nécessaire de le créer juste pour vérifier s'il est là. Quelque chose comme:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))
legoscia
la source
Intelligent - j'avais vu intern-softmais je n'avais pas pensé à l'utiliser de cette façon.
Dan
6

Je ne comprends peut-être pas la question correctement. Mais si vous voulez un mot - clé ( par exemple, vous voulez satisfaire keywordp), vous voulez que le symbole à interné dans le obarray mondial , obarray.

Il doit y être interné pour satisfaire keywordp, AFAICT, et le C-h f keywordpdit.

Donc, la réponse à votre question, AFAICT, est juste à utiliserintern .

J'ai l'impression que vous ne posez peut-être pas votre vraie question - semble être une question XY. Qu'essayez-vous vraiment de faire? (Peut-être poser cela comme une question distincte.)

[En réponse à votre commentaire selon lequel l'internement " n'est pas :keywordspécifique, car il s'applique à tous les symboles ": Correct, l'internement n'est pas spécifique aux mots clés. Mais l'internement (en obarray) et l'utilisation d'un symbol-namequi commence par :est spécifique aux mots clés.]

A dessiné
la source
C'est très certainement une question XY dans le sens où j'essaie de Y, mais je me suis vraiment intéressé à X dans ma tentative pour arriver à Y. Permettez-moi de réfléchir à la façon de poser la question sur Y de telle manière que ce soit utile aux autres aussi.
Dan
Génial. Ce sera utile. THX.
Drew
2

Voici une réponse partielle à cette question. La version courte et pas entièrement satisfaisante semble être: utiliser intern.

:key-1 satisfait à la fois:

(symbolp :key-1)                    ; => t
(keywordp :key-1)                   ; => t

Tout en (make-symbol ":key-1")satisfaisant le premier mais pas le second:

(symbolp (make-symbol ":key-1"))    ; => t
(keywordp (make-symbol ":key-1"))   ; => nil

Maintenant, le docstring pour make-symboldit qu'il va:

Renvoie un symbole non interne nouvellement alloué dont le nom est NAME.

Mmmkay, et le docstring pour keywordpdit qu'il va:

Renvoie tsi OBJECT est un mot-clé. Cela signifie qu'il s'agit d'un symbole avec un nom en caractères d'imprimerie commençant par : interné dans le tableau initial.

Il semble donc que interncela fonctionnera:

(assq (intern ":key-1") alist)      ; => (:key-1 "Key no. 1")

Parce internque:

Renvoie le symbole canonique dont le nom est STRING. S'il n'y en a pas, un est créé par cette fonction et renvoyé. Un deuxième argument facultatif spécifie le tableau à utiliser; il prend par défaut la valeur de obarray.

Mais cela ne semble pas être :keywordspécifique, car cela s'applique à tous les symboles. Par défaut, il semble également polluer le monde obarray, qui peut ou non être une grosse affaire.

Dan
la source