所以我试图添加一些东西到一些elisp模式钩子-具体来说,我想定义一个钩子的prettify-symbols-alist
,然后通过调用prettify-symbols-mode
专门激活它。
在任何情况下,我得到org-babel
导出值到一对列表从一个表,使用pairlis
将它们捆绑在一起作为一个列表,和add-hook
它到使用匿名函数所需的模式。
问题是,现在如果我使用一个全局变量,就像下面这样,它工作了:
(let ((token (quote ("not" "*" "/" "->" "map" "/=" "<=" ">=" "lambda")))
(code (quote (172 215 247 8594 8614 8800 8804 8805 955)))) ; Generated automatically using org-babel
(require 'cl)
(setq *globalvar (pairlis token code))
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(setq prettify-symbols-alist *globalvar)
(prettify-symbols-mode 1))))
但是如果我尝试不使用全局变量,通过这样做,它不起作用:
(let ((token (quote ("not" "*" "/" "->" "map" "/=" "<=" ">=" "lambda")))
(code (quote (172 215 247 8594 8614 8800 8804 8805 955)))) ; Generated automatically using org-babel
(let (localv)
(require 'cl)
(setq localv (pairlis token code))
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(setq prettify-symbols-alist localv)
(prettify-symbols-mode 1))))
我有点知道为什么:如果我C-h v emacs-lisp-mode-hook
,我会看到它指的是我在let
形式中使用的任何变量,当变量存在时,如*globalvar
,但当我使用localvar
时,它不再存在于其let
形式之外。但是我不确定如何强制对局部变量本身进行评估,因为我仍然在努力解决lisp中的许多概念,这些概念对我来说不是很清楚。
我错过了什么?我哪里出错了?
好了,这是我最后做的:
(let ((token (quote ("not" "*" "/" "->" "map" "/=" "<=" ">=" "lambda")))
(code (quote (172 215 247 8594 8614 8800 8804 8805 955))))
(require 'cl)
(lexical-let (localv)
(setq localv (pairlis token code))
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(setq prettify-symbols-alist localv)
(prettify-symbols-mode 1)))))
我最终使用phils的建议使用lexical-let
而不是Drew的建议,主要是因为我目前使用org-babel
将代码块缠结到我的源代码中(基本上我使用org-mode
来组织我的设置文件),并且似乎没有办法设置lexical-binding
文件本地变量-根据本页,您需要将其设置为第一行(使用;; -*- lexical-binding: t -*-
),我找不到一种方法来做到这一点。
无论如何,感谢每个帮助我解决这个问题的人!
首先将lexical-binding
设置为非nil
,否则localv
将成为钩子函数中的自由变量。最好将lexical-binding
设置为文件本地变量。
此外,代码中没有任何内容使localv
buffer-local。假设你想给它一个值,这个值对于处于该模式的缓冲区来说是局部的。绑定它的代码应该在模式中(即在缓冲区中)进行计算。
我喜欢这个解决方案。对于lexical-let
,对lambda
的调用(在add-hook
内部)生成一个闭包,正如您可以看到的,如果您输入M-x ielm RET
和emacs-lisp-mode-hook RET
来检查它的值。
你也可以像这样使用老式的反号:
(add-hook 'emacs-lisp-mode-hook
`(lambda ()
(setq prettify-symbols-alist ',localv)
(prettify-symbols-mode 1)))
(编辑)注意backtick
在lambda
之前,(如tarikq所提到的)quote-comma
在localv
之前。
实际上,我要说的不是"展开它然后引用它",而是"插入它的值(来自词法环境),然后引用它"。
如果你尝试这样做:
(macroexpand '`(lambda ()
(setq prettify-symbols-alist ',localv)
(prettify-symbols-mode 1)))
那么你将得到lisp在运行时实际执行的操作:
(cons 'lambda
(cons nil
(cons
(list 'setq 'prettify-symbols-alist (list 'quote localv))
'((prettify-symbols-mode 1)))))
,您将看到整个列表是如何构建的,以及localv
通常如何求值,即不引用(与符号'setq
和'prettify-symbols-alist
以及列表'((prettify-symbols-mode 1))
相比)