Jak stworzyć: słowa kluczowe?

16

P: Jak się tworzy i używa :keywords?

Rozważ (naiwnie, najwyraźniej) próbę uzyskania dostępu do następującej listy zabawek:

(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

Pierwszy klucz działa zgodnie z oczekiwaniami, ale drugi klucz nie. O ile nie ma oczywistej make-keywordfunkcji, jak można utworzyć i użyć słowa kluczowego?

Oryginalna motywacja: muszę przekształcić ciąg znaków w klucz wyszukiwania, który jest symbolem, na którym mogę putwłaściwości.

W trakcie formułowania tego pytania uzyskałem przynajmniej część odpowiedzi, którą zamieszczam osobno. Mam nadzieję, że jaśniejsze umysły niż moje mogą poprawić.

Dan
źródło
1
(eq :foo (read ":foo"))
abo-abo

Odpowiedzi:

9

Masz rację, że make-symbolutworzysz słowo kluczowe, które nie eqjest żadnym z istniejących słów kluczowych, i internmoże zanieczyścić globalną obarray nowym symbolem. Pomiędzy nimi masz intern-soft, który zwraca symbol, jeśli został już utworzony lub niljeśli nie:

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

Powinno to być odpowiednie dla twojego celu: jeśli słowo kluczowe nie istnieje, nie może być obecne na liście, więc nie trzeba go tworzyć, aby sprawdzić, czy ono istnieje. Coś jak:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))
legoscia
źródło
Sprytne - widziałem, intern-softale nie pomyślałem, aby użyć go w ten sposób.
Dan
6

Być może nie rozumiem poprawnie pytania. Ale jeśli chcesz słowa kluczowego (czyli chcesz, aby zaspokoić keywordp), to chce być symbolem internowany w globalnej obarray , obarray.

To musi być internowany tam do zaspokojenia keywordp, AFAICT, i C-h f keywordptak mówi.

Tak więc odpowiedź na twoje pytanie, AFAICT, jest tylko do użyciaintern .

Wydaje mi się, że być może nie zadajesz prawdziwego pytania - wygląda na pytanie XY. Co naprawdę próbujesz zrobić? (Być może stanowią to osobne pytanie.)

[W odpowiedzi na twój komentarz, że internowanie „ nie jest :keywordspecyficzne, ponieważ dotyczy wszystkich symboli ”: Prawidłowo, internowanie nie jest specyficzne dla słów kluczowych. Ale internowanie (in obarray) i korzystanie z symbol-namerozpoczynającego się od :jest specyficzne dla słów kluczowych.]

Rysował
źródło
Z pewnością jest to pytanie XY w tym sensie, że próbuję uzyskać Y, ale naprawdę zainteresowałem się X, gdy próbuję dostać się do Y. Pozwólcie mi zastanowić się, jak postawić pytanie o Y w taki sposób, że jest to przydatne również dla innych.
Dan
Świetny. To będzie pomocne. Dzięki.
Drew
2

Oto częściowa odpowiedź na to pytanie. Krótka i niezupełnie satysfakcjonująca wersja wygląda na: użyj intern.

:key-1 spełnia zarówno:

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

Wprawdzie (make-symbol ":key-1")spełnia pierwsze, ale nie drugie:

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

Teraz dokumentacja dla make-symbolmówi, że:

Zwraca nowo przydzielony nienaruszony symbol o nazwie NAZWA.

Mmmkay, a dokumentacja dla keywordpmówi, że:

Zwróć, tjeśli OBIEKT jest słowem kluczowym. Oznacza to, że jest to symbol z nadrukowaną nazwą rozpoczynającą się od : internowania w początkowej obarray.

Wygląda więc na to, że internzadziała:

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

Ponieważ internbędzie:

Zwraca symbol kanoniczny o nazwie STRING. Jeśli nie ma, funkcja jest tworzona przez tę funkcję i zwracana. Drugi opcjonalny argument określa obarray do użycia; domyślnie jest to wartość obarray.

Nie wydaje się to jednak :keywordspecyficzne, ponieważ dotyczy wszystkich symboli. Domyślnie wydaje się także, że zanieczyszcza globalność obarray, co może, ale nie musi być wielkim problemem.

Dan
źródło