如何创建:keywords?


16

问:如何创建和使用:keywords

考虑一下(显然是天真的)尝试访问以下玩具列表:

(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

第一个键可以按预期工作,但第二个键则不能。在没有明显make-keyword功能的情况下,如何创建和使用关键字?

原始动机:我需要将字符串转换为查找键,该键是我可以使用的符号put

在提出这个问题的过程中,我至少得到了一部分答案,我将分别发布。我希望有比我的人更聪明的想法可以改善它。


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

Answers:


9

正确的make-symbol做法是创建一个不存在eq于任何现有关键字的关键字,并intern可能用新符号污染全局数组。在它们之间,您有intern-soft,如果已经创建符号,或者尚未创建符号,则返回该符号nil

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

这应该适合您的目的:如果该关键字不存在,则该关键字不能出现在列表中,因此无需创建它只是检查其是否存在。就像是:

(let ((maybe-keyword (intern-soft ":key-1")))
  (and maybe-keyword (assq maybe-keyword alist)))

聪明-我见过intern-soft但没想到会用这种方式。

6

也许我没有正确理解这个问题。但是,如果您想要一个关键字(即,您想要满足keywordp),那么您希望将符号插入到全局obarrayobarray

必须在那里实习以满足keywordpAFAICT的要求C-h f keywordp

所以回答你的问题,AFAICT,只是为了使用intern

我觉得您可能不是在问真正的问题-似乎是XY问题。您到底想做什么?(也许将其作为一个单独的问题。)

[针对您的评论,实习生不是:keyword特定的,因为它适用于所有符号 “:正确,实习生并非特定于关键字。但是,实习(in obarray)和使用以symbol-name开头的a :特定于关键字。]


就我要尝试Y而言,这当然是一个XY问题,但在尝试进入Y时我对X真的很感兴趣。让我考虑一下如何以这样一种方式提出有关Y的问题对其他人也有用。

大。那会有所帮助。谢谢。
画了

2

这是该问题的部分答案。简短但不完全令人满意的版本似乎是:use intern

:key-1 同时满足:

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

虽然(make-symbol ":key-1")满足第一个条件但不满足第二个条件:

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

现在,的文档字符串make-symbol表示它将:

返回名称为NAME的新分配的未隔离符号。

Mmmkay,文档字符串keywordp表示它将:

t如果OBJECT是关键字,则返回。这意味着它是一个符号,其打印名称: 在初始obarray中以interned开头。

因此,似乎intern可行:

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

因为intern将:

返回名称为STRING的规范符号。如果不存在,则由该函数创建一个并返回。第二个可选参数指定要使用的数组。它的默认值为obarray

但这似乎并不:keyword具体,因为它适用于所有符号。默认情况下,它似乎也会污染global obarray,这可能会或可能不会很重要。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.