Emacs 在elisp中,如何将反引号应用于从文件读取的列表
我想要一个大的列表(想想emacs主题中的faces),并将其分解成单独文件中的小列表。我遇到的问题是,一旦读入列表,就将其应用到列表中 下面是我用来试验解决方案的代码:Emacs 在elisp中,如何将反引号应用于从文件读取的列表,emacs,elisp,Emacs,Elisp,我想要一个大的列表(想想emacs主题中的faces),并将其分解成单独文件中的小列表。我遇到的问题是,一旦读入列表,就将其应用到列表中 下面是我用来试验解决方案的代码: (defvar x 23) (defun read-from-file (file) (with-temp-buffer (insert-file-contents file) (read (current-buffer)))) ;;(defun apply-macro (macro arg-list)
(defvar x 23)
(defun read-from-file (file)
(with-temp-buffer
(insert-file-contents file)
(read (current-buffer))))
;;(defun apply-macro (macro arg-list)
;; (eval
;; `(,macro ,@(loop for arg in arg-list
;; collect `(quote ,arg)))))
(defvar parts (mapcar 'read-from-file (directory-files "./parts/" "parts/" "\.part$")))
;;(apply-macro 'backquote parts)
parts
此代码依赖于名为parts/
的子目录中的“数据”文件。以下是一些示例:
parts/one.part
`(“一”“二”“三”)(“十”,x“十二”)
注意:本例中的
,x
。我希望在从文件中读取表达式后对其求值。parts/two.part
(“四”“五”“六”)(2 4 6)(9 87 6))
部分/3.部分
(“七”“八”“九”))
(defvar parts(mapcar…)
问题是,一旦我在parts
变量中有了列表,我就找不到一种方法来计算,x
,因为如果整个列表被反引用,而不是从文件中读取的话
我在中尝试了建议。您可以在上面的代码中看到注释掉的apply macro
函数。当我运行它时,我得到:
Debugger entered--Lisp error: (wrong-number-of-arguments #[(structure) "\301!A\207" [structure backquote-process] 2 1628852] 3)
#[(structure) "\301!A\207" [structure backquote-process] 2 1628852]((quote (\` (("one" "two" "three") ("ten" (\, x) "twelve")))) (quote (("seven" "eight" "nine"))) (quote (("four" "five" "six") (2 4 6) (9 87 6))))
(backquote (quote (\` (("one" "two" "three") ("ten" (\, x) "twelve")))) (quote (("seven" "eight" "nine"))) (quote (("four" "five" "six") (2 4 6) (9 87 6))))
eval((backquote (quote (\` (("one" "two" "three") ("ten" (\, x) "twelve")))) (quote (("seven" "eight" "nine"))) (quote (("four" "five" "six") (2 4 6) (9 87 6)))))
apply-macro(backquote ((\` (("one" "two" "three") ("ten" (\, x) "twelve"))) (("seven" "eight" "nine")) (("four" "five" "six") (2 4 6) (9 87 6))))
eval-region(648 678 t #[257 "\300\242b\210\301\207" [(678) (apply-macro (quote backquote) parts)] 2 "\n\n(fn IGNORE)"]) ; Reading at buffer position 651
eval-defun-2()
#[257 "\211\203
反引号做了一些有趣的事情。在Emacs lisp中,读取准引号列表返回的值是以下结构的列表:
ELISP> (defvar x (car (read-from-string "`(1 2 ,x)")))
ELISP> (car x)
\`
ELISP> (cdr x)
((1 2
(\, x)))
ELISP> (caddr (cadr x))
(\, x)
ELISP> (consp (caddr (cadr x)))
t
因此,如果您打算使用准引号列表,您可能需要自己执行替换。例如,您可以执行以下操作:
(defun replace-item (item new-item seq)
(let ((found-item (member item seq)))
(when found-item
(setf (car found-item) new-item))
seq))
ELISP> (replace-item '(\, x) 'z (cadr x))
(1 2 z)
PS.Common Lisp使用逗号字符做了一些奇怪的事情,在读取相同的列表后,X
成为SB-IMPL::comma
类型的对象(在SBCL中):它既不是符号,也不是对
PPS。不知何故,读者计算器会特别处理这些准引号和逗号,以至于组合(eval(read))
不会产生与内部计算器相同的结果
有用的东西
在使用反引号和逗号的时候,我发现下面的方法很有效,尽管这是一个相当复杂的技巧
首先,不要重复引用你的结构:它不会造成任何伤害,但也不会引入任何东西
当您读取它时(使用文件中的read
或字符串中的read
),它将转换为:
ELISP> (setq x (car (read-from-string "(a b ,c)")))
(a b
(\, c))
现在,神奇的是:有一个宏backquote
进行替换,但它接受一个结构:它不计算其参数,因此要使其作用于x
必须执行以下操作:
ELISP> (let ((c 10)) (eval `(backquote ,x)))
(a b 10)
如您所见,(\,c)
已被所需的c
的本地绑定所取代
购买力平价。人们会期望从字符串“
(ab,c)”中读取将产生
(反引号(ab,c))`但事实并非如此
我希望这能提供答案。谢谢。看起来我会为我要替换的每个符号调用replace item
调用。例如,如果文件中的列表包含,x,y,那么我需要为每个符号调用replace item。我想我可以找到所有需要替换的逗号部分,并映射到它们或其他符号上ng,但如果有一种应用反引号的方法会更好。@HenryBone我想我找到了让Elisp做你想做的事情的方法:我已经更新了答案。@HenryBone事实上,它可以更简单:(let((c 10))(eval(car(从字符串“
(a b,c)”)=>(a b 10)`Thank you@mobiuseng.have tick.:-)