首页 > 解决方案 > 如何遍历 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 中的文字列表直到它为空?

标签: listlispelisp

解决方案


问题在于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列出 consesto-find和values可能会更惯用to-replace,但这至少应该让你回到路上。

请注意,它replacement-list是 的一部分let*,因此while在列表为空时结束。如果query-replace是 条件中的最后一个形式while,则循环将在没有找到匹配项时结束。请参阅其他线程


推荐阅读