关于make-symbol和assq,我在这里错过了什么?

时间:2013-04-28 05:43:45

标签: elisp

我正在尝试生成let块接受局部变量定义的相同结构但是遇到了一个墙:给定parse函数:

(defun parse (string)
  (mapcar (lambda (line)
            (let* ((k_v (split-string line "="))
                   (key (make-symbol (first k_v)))
                   (val (second k_v)))
              (list key val)))
          (split-string string "\n" t)))

我在lisp-interaction-mode中得到了与看起来类似的输出:

(setq alist (parse "foo=bar\nbaz=quux\n"))
((foo "bar") (baz "quux"))

鉴于......

(assq 'foo '((foo "bar") (baz "quux")))
(foo "bar")

......我希望下面会得到相同的结果 - 我错过了什么?

(assq 'foo alist)
nil

虽然如果Emacs版本很重要,我会感到惊讶,但我一直在OSX上的Emacs 24.2(9.0)中对此进行测试。

1 个答案:

答案 0 :(得分:6)

来自make-symbol文档:

(make-symbol NAME)

Return a newly allocated uninterned symbol whose name is NAME.
Its value and function definition are void, and its property list is nil.

您的assq正在将 interned 符号foo与一些名为foo的随机 uninterned 符号进行比较,其中(当然)会失败,因为它们不是同一个符号。

使用intern代替make-symbol(如下所示)可以解决您的问题。

(intern STRING &optional OBARRAY)

Return the canonical symbol whose name is STRING.
If there is none, one is created by this function and returned.
A second optional argument specifies the obarray to use;
it defaults to the value of `obarray'.
(defun parse (string)
  (mapcar (lambda (line)
            (let* ((k_v (split-string line "="))
                   (key (intern (first k_v))) ; change here
               (val (second k_v)))
              (list key val)))
          (split-string string "\n" t)))

(intern "foo")会返回 interned 符号foo,该符号将添加到您的列表中,以便(assq 'foo alist)正常工作。

(在Win7上测试我的Emacs 24.2.1。)