Emacs 为什么(commandp';(customizeoption';foo))为零?

Emacs 为什么(commandp';(customizeoption';foo))为零?,emacs,lisp,elisp,Emacs,Lisp,Elisp,我想将某个变量的自定义选项绑定到一个键,因为我需要经常更改它。我有两个选择: (global-set-key (kbd "<f12>") '(lambda() (interactive) (customize-option 'my-variable) ) ) (global-set-key (kbd "<f12>") '(customize-option 'my-variable ) (全局设置键(kbd“”)”(lambda()(交互式)(自定义选项“我的变量”))

我想将某个变量的
自定义选项
绑定到一个键,因为我需要经常更改它。我有两个选择:

(global-set-key (kbd "<f12>") '(lambda() (interactive) (customize-option 'my-variable) ) )
(global-set-key (kbd "<f12>") '(customize-option 'my-variable )
(全局设置键(kbd“”)”(lambda()(交互式)(自定义选项“我的变量”))
(全局设置键(kbd“”)”(自定义选项“我的变量”)
第一个有效,第二个无效,因为
commandp
抱怨
customize option
不是命令。为什么?据我所知,
customize option
是一个交互式功能,所以
commandp
应该是
t

自定义选项是一个交互式编译的Lisp函数

这是必然的

(自定义选项符号)

自定义符号,它必须是用户选项变量


这是一个非命令的表单
(自定义选项“我的变量”)
。您不能绑定到任意带引号的表单,就像绑定到文字字符串或未绑定的符号一样。其中一些绑定可能很有用,但绕过这些限制并不困难。如果您觉得难以接受,请编写宏。(俗话说,现在你有两个问题。)

这是形式
(自定义选项“我的变量”)
这不是命令。你不能绑定到任意带引号的表单,就像绑定到文字字符串或未绑定的符号一样。绑定到其中一些表单会很有用,但绕过这些限制并不困难。如果你觉得难以使用宏,就编写宏。(俗话说,现在你有两个问题。)全局设置键的第二个参数必须是命令定义,通常是命名交互函数的符号。交互函数是以
(交互)
表单开头的函数。例如:

(defun delete-to-end ()
  "Delete text from point to the end of buffer."
  (interactive)
  (delete-region (point) (point-max)))
这定义了一个交互功能,并将其分配给符号
delete to end
。之后,
delete to end
是一个有效的命令,您可以将其传递给
全局设置键

(global-set-key [f12] 'delete-to-end)
如果没有
(交互式)
行,
删除结束
仍将命名一个可从Lisp程序调用的函数,但它将不是“命令”。由于它标记为交互式,
(commandp'delete to end)
返回true,并且M-x delete to end工作

交互函数不需要绑定到符号,它们可以是匿名的。与任何其他匿名函数一样,它们是使用
lambda
表单创建的,但对于命令,它还必须包含
(交互)
。匿名命令可以作为第二个参数传递给
全局设置键
,而无需将其分配给符号,因此以下定义与上面的定义等效:

(global-set-key [f12]
                (lambda ()
                  "Delete text from point to the end of buffer."
                  (interactive)
                  (delete-region (point) (point-max))))
…只是它的可读性稍差,用C-h C检查时看起来更难看 或者C-hk


在您的情况下,第一次调用
全局设置键
时给出了一个有效的命令(引用的
lambda
表单本身就是一个有效的函数),但第二次调用不是,它给出了一个两元素列表,既不能调用也不能满足标记为“交互式”的要求.

全局设置键的第二个参数必须是命令定义,通常是命名交互函数的符号。交互函数是以
(交互)
表单开头的函数。例如:

(defun delete-to-end ()
  "Delete text from point to the end of buffer."
  (interactive)
  (delete-region (point) (point-max)))
这定义了一个交互功能,并将其分配给符号
delete to end
。之后,
delete to end
是一个有效的命令,您可以将其传递给
全局设置键

(global-set-key [f12] 'delete-to-end)
如果没有
(交互式)
行,
删除结束
仍将命名一个可从Lisp程序调用的函数,但它将不是“命令”。由于它标记为交互式,
(commandp'delete to end)
返回true,并且M-x delete to end工作

交互函数不需要绑定到符号,它们可以是匿名的。与任何其他匿名函数一样,它们是使用
lambda
表单创建的,但对于命令,它还必须包含
(交互)
。匿名命令可以作为第二个参数传递给
全局设置键
,而无需将其分配给符号,因此以下定义与上面的定义等效:

(global-set-key [f12]
                (lambda ()
                  "Delete text from point to the end of buffer."
                  (interactive)
                  (delete-region (point) (point-max))))
…只是它的可读性稍差,用C-h C检查时看起来更难看 或者C-hk


在您的情况下,第一次调用
全局设置键
时给出了一个有效的命令(引用的
lambda
表单本身就是一个有效的函数),但第二次调用不是,它给出了一个两元素列表,既不能调用也不能满足标记为“交互式”的要求.

听起来不错。宏解决方案会是什么样子?还是一个elisp新手……在最简单的情况下,类似于
(defmacro bind to(key seq)(全局设置键,key(function)(lambda(nil),@seq)))
如果我的宏技能没有严重生锈的话。不过,宏很容易让你陷入沉重的伏都教。好吧,我想我可以坚持我的上述解决方案。至少现在我明白了为什么我不能在没有lambda的情况下绑定它。听起来不错。宏解决方案看起来会是什么样子?还是有点像elisp新手……最简单的情况下,有些类似于
(defmacro绑定到(key seq)(全局设置键,key(函数(lambda(nil),@seq)))
如果我的宏技能没有严重生锈的话。但是宏很容易让你陷入沉重的伏都教中。好吧,我想我可以坚持我上面的解决方案。至少现在我明白了为什么没有lambda就不能绑定它。请不要引用lambda表达式。例如,使用
(lambda…
而不是
(lambda…)
。两者都有效,但添加引号是一个坏习惯。请不要引用lambda表达式。即,使用
(lambda…
而不是
”(lambda…
。两者都有效,但添加引号是一个坏习惯。