[英]How can I insert into the middle of a list in ELisp?
我有以下數據結構作為 ELisp 變量( ispell-tex-skip-alists
):
((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2")))
我可以使用cddadr
隔離我需要的列表部分,但我需要向此列表添加一個元素:
((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2")
("env3" . "endenv3")))
我試過add-to-list
,但顯然我需要add-to-list
的cddadr
部分的符號名稱(我可以在技術上優化為cadr
)才能使add-to-list
工作。
我怎樣才能達到我需要的結果?
最佳嘗試:
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "\\\\end[ \n]*{[ \n]*%s" (if star "\\*?") "[ \n]*}")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(setcdr (last env-list)
(cons (format start env)
(format end env))))))
我假設您的方法中缺少一個list
:
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "\\\\end[ \n]*{[ \n]*%s" (if star "\\*?") "[ \n]*}")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(setcdr (last env-list)
(list
(cons (format start env)
(format end env)))))))
在您的版本中,相關列表的結構發生了變化。 在修改之前,它是一個缺點列表。 修改后是一個混合列表。 大多數條目都是 conses,但最后一個 car 是一個字符串,最后一個 cdr 也是一個字符串。
或者setcdr
和last
,您可以使用nconc
:
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "\\\\end[ \n]*{[ \n]*%s" (if star "\\*?") "[ \n]*}")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(nconc env-list
(list
(cons (format start env)
(format end env)))))))
接下來是一個測試。 為了與原始發布的想要的結果進行比較,我將"\\\\\\\\end[ \\n]*{[ \\n]*%s"
替換為"end%s"
和"[ \\n]*}"
""
在LaTeX-ispell-skip-environment
。 在的端progn
的結果(LaTeX-ispell-skip-environment "env3")
與測試equal
針對想要的結果。 測試返回t
。
(progn
(defun LaTeX-ispell-skip-environment (env &optional star)
(let ((start (concat "%s" (if star "\\*?")))
(end (concat "end%s" (if star "\\*?") "")))
(let ((env-list (cddadr ispell-tex-skip-alists)))
(setcdr (last env-list)
(list
(cons (format start env)
(format end env)))))))
(setq ispell-tex-skip-alists
'((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2"))))
(LaTeX-ispell-skip-environment "env3")
(equal ispell-tex-skip-alists
'((("---" ispell-tex-arg-end 2)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end)
("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end)
("---" . "---"))
(("---" ispell-tex-arg-end 0)
("---" ispell-tex-arg-end 2)
("env1" . "endenv1")
("env2" . "endenv2")
("env3" . "endenv3")))))
為了更籠統地回答標題中提到的問題,這里有一個函數,它在列表的第 n 個位置插入一個元素:
(defun insert-into-list (list el n)
"Insert into list LIST an element EL at index N.
If N is 0, EL is inserted before the first element.
The resulting list is returned. As the list contents is mutated
in-place, the old list reference does not remain valid."
(let* ((padded-list (cons nil list))
(c (nthcdr n padded-list)))
(setcdr c (cons el (cdr c)))
(cdr padded-list)))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.