¿Cómo crear: palabras clave?

16

P: ¿Cómo se crea y usa :keywords?

Considere un intento (ingenuo, aparentemente) de acceder a la siguiente lista de juguetes:

(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 primera clave funciona como se esperaba, pero la segunda clave no. En la medida en que no exista una make-keywordfunción obvia , ¿cómo se crea y usa una palabra clave?

Motivación original: necesito transformar una cadena en una clave de búsqueda que es un símbolo en el que puedo putpropiedades.

En el proceso de formulación de esta pregunta, llegué al menos a parte de la respuesta, que publico por separado. Espero que mentes más brillantes que las mías puedan mejorarlo.

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

Respuestas:

9

Tiene razón al make-symbolcrear una palabra clave que no corresponde eqa ninguna palabra clave existente, y internpodría contaminar la matriz global con el nuevo símbolo. Entre esos, tienes intern-soft, que devuelve el símbolo si ya se ha creado, o nilsi no:

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

Esto debería ser adecuado para su propósito: si la palabra clave no existe, no puede estar presente en la lista, por lo que no es necesario crearla solo para verificar si está allí. Algo como:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))
legoscia
fuente
Inteligente: lo había visto intern-softpero no había pensado en usarlo de esta manera.
Dan
6

Quizás no entiendo la pregunta correctamente. Pero si quieres una palabra clave (es decir, que quieren satisfacer keywordp), entonces usted quiere que el símbolo que se encuentra internado en el obarray mundial , obarray.

Se debe ser internadas para satisfacer keywordp, AFAICT, y C-h f keywordplo dice.

Entonces la respuesta a su pregunta, AFAICT, es solo para usarintern .

Siento que tal vez no estás haciendo tu pregunta real, parece una pregunta XY. ¿Qué es lo que realmente intentas hacer? (Tal vez plantee eso como una pregunta separada).

[En respuesta a su comentario de que las prácticas " no son :keywordespecíficas, ya que se aplican a todos los símbolos ": Correcto, las prácticas no son específicas para las palabras clave. Pero el internado (en obarray) y el uso de un symbol-nameque comienza con :es específico para las palabras clave.]

Dibujó
fuente
Sin duda, es una pregunta XY en el sentido de que estoy tratando de Y, pero realmente me interesé en X en mi intento de llegar a Y. Permítanme reflexionar sobre cómo plantear la pregunta sobre Y de tal manera que sea útil para otros también.
Dan
Excelente. Eso será de ayuda. Gracias.
Dibujó
2

Aquí hay una respuesta parcial a esta pregunta. La versión corta y no del todo satisfactoria parece ser: uso intern.

:key-1 satisface ambos:

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

Mientras (make-symbol ":key-1")satisface el primero pero no el segundo:

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

Ahora, la cadena de documentación make-symboldice que:

Devuelve un símbolo no asignado asignado recientemente cuyo nombre es NAME.

Mmmkay, y la cadena de documentación para keywordpdice que:

Regrese tsi OBJECT es una palabra clave. Esto significa que es un símbolo con un nombre impreso que comienza con : internados en la matriz inicial.

Entonces parece que internfuncionará:

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

Porque intern:

Devuelve el símbolo canónico cuyo nombre es STRING. Si no hay ninguno, esta función crea uno y se devuelve. Un segundo argumento opcional especifica la matriz a utilizar; su valor predeterminado es obarray.

Pero esto no parece ser :keywordespecífico, ya que se aplica a todos los símbolos. Por defecto, también parece contaminar lo global obarray, lo que puede o no ser un gran problema.

Dan
fuente