Emacs - 如何用let-bound变量替换列表的第n个元素

时间:2014-03-16 17:12:32

标签: emacs elisp

我没有找到任何关于如何替换列表的nth元素的示例,而不先添加每个元素一个一个)一个),函数为add-to-ordered-list - 例如(add-to-ordered-list 'the-list 'a 1)。这需要随后删除元素 - 例如(delq a the-list)。该过程的第三步是添加 new 元素 - 例如(add-to-ordered-list 'the-list "HELLO-WORLD!" 1)。由于以下名为variable-list-example的函数使用了26个元素,我正在寻找一种比首先添加所有26个元素(逐个)更好的方法来基本上为每个元素分配一个位置编号。函数add-to-ordered-list使用与标准nth元素方法不同的数字赋值,其中第一个元素的值为0,而add-to-ordered-list使用的值为1 add-to-ordered-list表示第一个元素。以下是'(http://www.gnu.org/software/emacs/manual/html_node/elisp/List-Variables.html

文档的链接

此外,在列表开头使用组合my-variable似乎可以防止在列表中使用let-bound变量 - 例如,let-bound变量在列表中显示为{{1}而不是HELLO-WORLD!。我发现的唯一解决方法是上面提到的使用add-to-ordered-list的示例 - 这是一个漫长的三步过程(即,在每个元素中添加逐个首先)。

要解决这两个问题,我正在寻求一些帮助,请替换17th的{​​{1}}元素(字母为the-list { {1}}(即r)。


my-variable

列表

HELLO-WORLD!

nth ELEMENT - CHEAT SHEET / LEGEND

(defun variable-list-example ()
(interactive)
  (let* (
      (my-variable "HELLO-WORLD!")
      (the-list '(a b c d e f g h i j k l m n o p q r s t u v w x y z)))
    ;; replace the 17th element of `the-list` with `my-variable`
    (message "Presto -- this is your new list:  %s" the-list)
  ))

3 个答案:

答案 0 :(得分:11)

您需要使用setcarnthcdr

(setcar (nthcdr 17 the-list) my-variable)

更常见的类似于lisp的方法是使用Generalized Variables

(setf (nth 17 the-list) my-variable)

答案 1 :(得分:5)

Emacs的概念为Generalized Variables,它基本上允许您使用setf更改任意存储位置。例如,您可以更改列表的carcdr个位置,包括car返回的nth。因此,以下代码

(let ((foo 10)
      (l '(1 2 3 4 5 6 7 8)))
  (setf (nth 4 l) foo)
  l)

将返回列表(1 2 3 4 10 6 7 8)

要将变量直接放入引用列表,您必须更改引用的类型。 standard quote '会在引用的表达式中禁止任何评估

然而,特殊Backquote允许您评估引用表达式中的表达式:

(let* ((foo 10)
      (l `(1 2 3 4 5 ,foo 7 foo)))
  l)

前导逗号标记后续的评估表达式,而没有前导逗号的表达式将按字面意思进行。在上面的示例中,将评估列表中第一次出现的foo,因此将替换为10,而第二次出现在列表中的字面上结束。

答案 2 :(得分:0)

添加一个专门针对 add-to-ordered-list 的迟到答案,因为我认为它的作用和工作方式存在混淆。

add-to-ordered-list 允许您为单个列表元素指定(记录)特定顺序。

但是列表也可以包含没有为它们记录特定顺序的元素。这些元素总是放在列表的末尾,在所有具有特定记录顺序的元素之后。

如果你想替换一个有记录顺序的元素,那么你需要从列表中删除它并添加它的替换(这是你猜的)。

(add-to-ordered-list 'the-list 'a 1) ; Records order 1 for element (symbol) a. 
(delq a the-list) ; Removes a from the list.
(add-to-ordered-list 'the-list 'HELLO 1) ; Records order 1 for element (symbol) HELLO.

要补充一些东西,以帮助澄清一点:

  1. 您不能使用字符串元素,例如 "HELLO",因为记录元素的顺序要求使用 eq(而不是 equal 或 {{1} }}).

  2. 您可以从元素中删除记录的顺序,而不是从列表中删除元素。如果这样做,该元素将保留在列表中,但会移动到任何已记录订单的元素之后。这不是您在这里想要的(您想替换它),但要知道这是可能的。您可以通过使用元素和 no string= 值(或 add-to-ordered-list 值)调用 ORDERED 来实现此目的。

  3. 为元素记录的顺序不需要为所有元素指定(见上文),它们不需要是连续的。重要的是它们可以在数字上进行比较,因此可以对它们的元素进行排序。例如,您可以添加元素 nilab(c a b)`,因为 6 < 12 < 42.

  4. 您甚至可以为多个列表元素记录相同的顺序,在这种情况下,这些元素在列表中是连续的,但它们之间的顺序并不重要。您可以将记录的订单视为桶或分数。所有得分为 3 的元素出现在列表中所有得分为 7 的元素之前,得分为 3(或 7)的元素是连续的。

另见this emacs.SE question