如何遍历 Emacs lisp 中的文字列表?
How to iterate through a list of literals in Emacs lisp?
我想替换 Emacs 缓冲区中的文本,这个函数有效:
(defun sanitize-md ()
"Replace characters."
(interactive)
(query-replace "\" "/" nil (point-min) (point-max))
(query-replace "fi" "fi" nil (point-min) (point-max))
)
我想用一个列表重构它:
(defun sanitize-md ()
"Replace characters."
(interactive)
(let (replacement-list '("\" "/" "fi" "fi"))
(while (progn
(let* (
(to-find (pop replacement-list))
(to-replace (pop replacement-list))
)
(query-replace to-find to-replace nil (point-min) (point-max)))
(replacement-list)
))))
但这会引发错误 Invalid function: "\"
,即使我引用了列表的声明。我想我对列表开头的 LISP 引号和函数系统感到困惑,所以我尝试 (let (replacement-list '(list "\" "/" "fi" "fi"))
并得到另一个错误 Wrong type argument: stringp, nil
.
如何遍历 LISP 中的文字列表直到它为空?
问题出在 let
表单的语法上。第一个参数应该是列表的列表,而不仅仅是一个列表。
另外,您需要使用 (interactive "*")
来避免尝试修改只读的内容。而 let*
形式(你已经使用了正确的语法!)已经是一个单一的形式,所以你可以去掉 progn
.
最后,replacement-list
不是一个函数,所以你应该在最后一个表达式中去掉它周围的括号。
(defun sanitize-md ()
"Replace characters."
(interactive "*")
(let ((replacement-list '("\" "/" "fi" "fi")))
(while (let* ((to-find (pop replacement-list))
(to-replace (pop replacement-list)) )
(query-replace to-find to-replace nil (point-min) (point-max))
replacement-list))) ))
使 replacement-list
成为具有 to-find
和 to-replace
值的 conses 列表可能更惯用,但这至少应该让你回到路上。
注意 replacement-list
是 let*
的一部分,所以当列表为空时 while
结束。如果query-replace
是while
条件中的最后一个形式,没有匹配到则循环结束。参见 this other thread。
您可以使用 the dolist
macro 轻松遍历模式列表及其替换。在下面的解决方案中,我在列表中将它们配对,以便在每次迭代时都可以访问它们:
(defun sanitize-md ()
"Replace characters."
(interactive "*")
(dolist (from-to '(("\" "/") ("fi" "fi")))
(query-replace (car from-to) (cdr from-to) nil (point-min) (point-max))))
我想替换 Emacs 缓冲区中的文本,这个函数有效:
(defun sanitize-md ()
"Replace characters."
(interactive)
(query-replace "\" "/" nil (point-min) (point-max))
(query-replace "fi" "fi" nil (point-min) (point-max))
)
我想用一个列表重构它:
(defun sanitize-md ()
"Replace characters."
(interactive)
(let (replacement-list '("\" "/" "fi" "fi"))
(while (progn
(let* (
(to-find (pop replacement-list))
(to-replace (pop replacement-list))
)
(query-replace to-find to-replace nil (point-min) (point-max)))
(replacement-list)
))))
但这会引发错误 Invalid function: "\"
,即使我引用了列表的声明。我想我对列表开头的 LISP 引号和函数系统感到困惑,所以我尝试 (let (replacement-list '(list "\" "/" "fi" "fi"))
并得到另一个错误 Wrong type argument: stringp, nil
.
如何遍历 LISP 中的文字列表直到它为空?
问题出在 let
表单的语法上。第一个参数应该是列表的列表,而不仅仅是一个列表。
另外,您需要使用 (interactive "*")
来避免尝试修改只读的内容。而 let*
形式(你已经使用了正确的语法!)已经是一个单一的形式,所以你可以去掉 progn
.
最后,replacement-list
不是一个函数,所以你应该在最后一个表达式中去掉它周围的括号。
(defun sanitize-md ()
"Replace characters."
(interactive "*")
(let ((replacement-list '("\" "/" "fi" "fi")))
(while (let* ((to-find (pop replacement-list))
(to-replace (pop replacement-list)) )
(query-replace to-find to-replace nil (point-min) (point-max))
replacement-list))) ))
使 replacement-list
成为具有 to-find
和 to-replace
值的 conses 列表可能更惯用,但这至少应该让你回到路上。
注意 replacement-list
是 let*
的一部分,所以当列表为空时 while
结束。如果query-replace
是while
条件中的最后一个形式,没有匹配到则循环结束。参见 this other thread。
您可以使用 the dolist
macro 轻松遍历模式列表及其替换。在下面的解决方案中,我在列表中将它们配对,以便在每次迭代时都可以访问它们:
(defun sanitize-md ()
"Replace characters."
(interactive "*")
(dolist (from-to '(("\" "/") ("fi" "fi")))
(query-replace (car from-to) (cdr from-to) nil (point-min) (point-max))))