Como criar: palavras-chave?

16

P: Como alguém cria e usa :keywords?

Considere uma tentativa (ingênua, aparentemente) de acessar o seguinte lista de brinquedos:

(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

A primeira chave funciona conforme o esperado, mas a segunda chave não. Na medida em que não existe uma make-keywordfunção óbvia , como alguém cria e usa uma palavra-chave?

Motivação original: preciso transformar uma string em uma chave de pesquisa que seja um símbolo no qual eu possa putpropriedades.

No processo de formular esta pergunta, recebi pelo menos parte da resposta, que estou publicando separadamente. Espero que mentes mais brilhantes que as minhas possam melhorar isso.

Dan
fonte
1
(eq :foo (read ":foo"))
abo-abo 27/02

Respostas:

9

Você está certo ao make-symbolcriar uma palavra-chave que não pertence eqa nenhuma palavra-chave existente e internpode poluir a matriz global com o novo símbolo. Entre eles, você tem intern-soft, que retorna o símbolo se ele já foi criado ou nilse não:

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

Isso deve ser adequado ao seu objetivo: se a palavra-chave não existir, ela não poderá estar presente na lista, portanto, não será necessário criá-la apenas para verificar se ela existe. Algo como:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))
legoscia
fonte
Inteligente - eu já tinha visto, intern-softmas não tinha pensado em usá-lo dessa maneira.
Dan
6

Talvez eu não esteja entendendo a pergunta corretamente. Mas se você quer uma palavra-chave (ou seja, você quer para satisfazer keywordp), então você quer que o símbolo a ser internado no obarray mundial , obarray.

Ele deve ser internado lá para satisfazer keywordp, AFAICT, e C-h f keywordpdiz isso.

Portanto, a resposta para sua pergunta, AFAICT, é apenas para usarintern .

Sinto que você talvez não esteja fazendo sua pergunta real - parece uma pergunta XY. O que você realmente está tentando fazer? (Talvez faça isso como uma pergunta separada.)

[Em resposta ao seu comentário, a internação " não é :keywordespecífica, pois se aplica a todos os símbolos ": correta, a internação não é específica de palavras-chave. Mas inserir (in obarray) e usar um symbol-nameque comece com :é específico para palavras-chave.]

Desenhou
fonte
É certamente uma pergunta XY no sentido em que estou tentando Y, mas fiquei realmente interessada em X na minha tentativa de chegar a Y. Deixe-me pensar um pouco sobre como fazer a pergunta sobre Y de tal maneira que seja útil para os outros também.
Dan
Ótimo. Isso será útil. Valeu.
Drew
2

Aqui está uma resposta parcial a esta pergunta. A versão curta e não totalmente satisfatória parece ser: use intern.

:key-1 satisfaz ambos:

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

Embora (make-symbol ":key-1")satisfaça o primeiro, mas não o segundo:

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

Agora, a doutrina para make-symboldiz que irá:

Retorne um símbolo não interno recém-alocado cujo nome é NAME.

Mmmkay, e a doutrina para keywordpdiz que irá:

Retorne tse OBJECT for uma palavra-chave. Isso significa que é um símbolo com um nome de impressão começando com : internado na matriz inicial.

Então parece que internvai funcionar:

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

Porque internirá:

Retorne o símbolo canônico cujo nome é STRING. Se não houver, um será criado por essa função e retornado. Um segundo argumento opcional especifica a matriz a ser usada; o padrão é o valor de obarray.

Mas isso não parece ser :keywordespecífico, pois se aplica a todos os símbolos. Por padrão, ele também parece poluir o global obarray, que pode ou não ser um grande negócio.

Dan
fonte