Wie erstelle ich: Keywords?

16

F: Wie erstellt und verwendet man :keywords?

Betrachten Sie einen (naiven, anscheinend) Versuch, auf die folgende Spielzeugliste zuzugreifen:

(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

Der erste Schlüssel funktioniert wie erwartet, der zweite Schlüssel jedoch nicht. make-keywordWie erstellt und verwendet man ein Schlüsselwort, sofern es keine offensichtliche Funktion gibt?

Ursprüngliche Motivation: Ich muss eine Zeichenfolge in einen Suchschlüssel umwandeln, der ein Symbol ist, auf das ich putEigenschaften anwenden kann .

Bei der Formulierung dieser Frage habe ich zumindest einen Teil der Antwort erhalten, die ich separat veröffentliche. Ich hoffe, dass ein besserer Verstand als meiner es verbessern kann.

Dan
quelle
1
(eq :foo (read ":foo"))
abo-abo

Antworten:

9

Sie haben Recht, dass make-symbolein Keyword erstellt wird eq, das keinem vorhandenen Keyword entspricht, und internmöglicherweise das globale Objekt mit dem neuen Symbol verunreinigt. Dazwischen haben Sie intern-soft, was das Symbol zurückgibt, wenn es bereits erstellt wurde oder nilnicht:

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

Dies sollte für Ihren Zweck geeignet sein: Wenn das Schlüsselwort nicht vorhanden ist, kann es nicht in der Alist vorhanden sein, sodass es nicht erstellt werden muss, um zu überprüfen, ob es vorhanden ist. Etwas wie:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))
Legoscia
quelle
Clever - ich hatte es gesehen, intern-softaber nicht daran gedacht, es so zu benutzen.
Dan
6

Vielleicht verstehe ich die Frage nicht richtig. Wenn Sie jedoch ein Schlüsselwort möchten (dh, Sie möchten erfüllen keywordp), möchten Sie, dass das Symbol im globalen obarray interniert wird obarray.

Es muss dort interniert werden, um zu befriedigen keywordp, AFAICT, und C-h f keywordpsagt es auch.

Die Antwort auf Ihre Frage, AFAICT, ist also nur zu verwendenintern .

Ich habe das Gefühl, dass Sie Ihre eigentliche Frage vielleicht nicht stellen - scheint eine XY-Frage zu sein. Was versuchst du wirklich zu tun? (Vielleicht stellen Sie das als separate Frage.)

[Als Antwort auf Ihre Bemerkung, dass Internierung " nicht :keywordspezifisch ist, da sie für alle Symbole gilt ": Richtig, Internierung ist nicht spezifisch für Schlüsselwörter. Internieren (in obarray) und Verwenden von a symbol-name, das mit "" beginnt, :ist jedoch spezifisch für Schlüsselwörter.]

Drew
quelle
Es ist mit Sicherheit eine XY-Frage in dem Sinne, dass ich es mit Y versuche, aber ich habe mich wirklich für X interessiert, um zu Y zu gelangen nützlich auch für andere.
Dan
Groß. Das wird hilfreich sein. Danke.
Drew
2

Hier ist eine teilweise Antwort auf diese Frage. Die kurze und nicht ganz befriedigende Version scheint zu sein: use intern.

:key-1 befriedigt beide:

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

Während (make-symbol ":key-1")erfüllt die erste, aber nicht die zweite:

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

Nun, die Docstring für make-symbolsagt, dass es wird:

Gibt ein neu zugewiesenes nicht internes Symbol zurück, dessen Name NAME ist.

Mmmkay, und der Docstring für keywordpsagt, dass es wird:

Rückgabe, twenn OBJECT ein Schlüsselwort ist. Dies bedeutet, dass es sich um ein Symbol mit einem : Drucknamen handelt, der mit "Interned" (Interniert) im ursprünglichen Feld beginnt.

So scheint es, dass internes funktionieren wird:

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

Denn internwird:

Geben Sie das kanonische Symbol mit dem Namen STRING zurück. Wenn es keine gibt, wird eine von dieser Funktion erstellt und zurückgegeben. Ein zweites optionales Argument gibt das zu verwendende Objekt an. Der Standardwert ist obarray.

Dies scheint jedoch nicht :keywordspezifisch zu sein, da es für alle Symbole gilt. Standardmäßig scheint es auch die globale Umwelt zu verschmutzen obarray, was eine große Sache sein kann oder nicht.

Dan
quelle