关于define-key(以及何时引用参数的问题)令人困惑的事情

时间:2009-10-28 10:19:37

标签: emacs lisp elisp quotes

使用define-key时似乎不应该引用KEYMAP。

(define-key org-remember-mode-map "\C-c\C-r" 'org-remember-kill)

我很困惑因为我认为未引用的函数的所有参数都会被评估,并且根据帮助,define-key是一个函数,而不是一个宏。我不明白为什么在调用define-key后可以修改KEYMAP的值。

(defun increment-value (a)
  (setq a (+ 1 a)))

(setq my-num 10)

(increment-value my-num)

my-num ; ===> 10

更新:答案解释了一切,但对于那些仍然困惑的人,请让我用更多的例子来解决。

上面的增量值示例等同于:

(let ((n 0))
  (print n) ; prints 0
  (let ((a n))
    (setq a (+ 1 a))
    (print a) ; prints 1
    )
  (print n) ; prints 0
  )

我认为,上面发生的事情与这个地图示例中发生的情况类似:

(let ((some-map '(1 2)))
  (print some-map) ; prints (1 2)
  (let ((a some-map))
    (setq a (list 4 (second a)))
    (print a) ; prints (4 2)
    )
  (print some-map) ; prints (1 2)
  )

define-key中发生的事情类似于第二个some-map示例:

(let ((some-map '(1 2)))
  (print some-map) ; prints (1 2)
  (let ((a some-map))
    (setcar a 4)
    (print a) ; prints (4 2)
    )
  (print some-map) ; prints (4 2)
  )

现在再次阅读这三个例子,你会得到它。另请阅读http://www.emacswiki.org/emacs/ListModification

3 个答案:

答案 0 :(得分:2)

你的价值和名称价值映射令人困惑。

在增量值函数中,您不会像更改名称a到新值的映射一样更改a的值。

从根本上说,没有办法改变10的值.10是10!

但在第一种情况下,您可以将名称org-remember-mode-map的映射修改为完全不同的地图(设置新值),也可以更改指向的地图该名称(当前值)。这就是define-key的作用。

插图:

(setq a '(1 2)) -> (1 2)
(setcar a 4) -> 4
a -> (4 2)

答案 1 :(得分:2)

您实际上并未更改'org-remember-map(指向特定列表结构的指针),您正在修改实际结构。有关修改列表的详细信息,请阅读this info page

具体而言,如果您查看'make-keymap的文档:

  

(make-keymap& optional string)

     

构造并返回一个新的键映射   表单(键映射CHARTABLE.ALIST)。   CHARTABLE是一个char表   所有字符的绑定   没有修饰语。其中的所有条目   最初是零,意思是“命令   undefined“.ALIST是一个关联列表   它包含功能绑定   键,鼠标事件和任何其他   输入中出现的东西   流。最初,ALIST是零。

你会看到keymap是一个包含三个元素的列表。让我为你画(yay M-x artist-mode):

 org-remember-map
    |
    |
    v
 +----+----+    +----+----+
 | |  |  --+--->+  / | \  |
 +-+--+----+    +-/--+--\-+
   |              |     |
   v              v     v
keymap      CHARTABLE  ALIST

因此,'org-remember-map的值类似于上面的结构,当你定义一个键时,你正在做的是改变结构的ALIST blob部分中指向的内容

答案 2 :(得分:1)

你写的一切都是完全正确的。您缺少的是列表(键映射表示为列表)本身不是值,而是值的容器。因此,您可以将列表传递给函数并使该函数更改列表的值,但您拥有的列表仍然是相同的列表。

所有详细信息都在elisp手册的Cons Cell Type部分。