【问题标题】:Emacs -- How to replace nth element of a list with a let-bound variableEmacs -- 如何用 let-bound 变量替换列表的第 n 个元素
【发布时间】:2014-03-16 17:12:32
【问题描述】:

我没有找到任何示例,说明如何在不先添加每个元素一个接一个) 与函数 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

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

为了解决这两个问题,我正在寻求一些帮助,请替换the-list17th 元素(即字母r my-variable(即@ 987654342@).


(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)
  ))

名单

'(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)

第 n 个元素 -- 备忘单/图例

element 0:   a
element 1:   b
element 2:   c
element 3:   d
element 4:   e
element 5:   f
element 6:   g
element 7:   h
element 8:   i
element 9:   j
element 10:  k
element 11:  l
element 12:  m
element 13:  n
element 14:  o
element 15:  p
element 16:  q
element 17:  r
element 18:  s
element 19:  t
element 20:  u
element 21:  v
element 22:  w
element 23:  x
element 24:  y
element 25:  z

【问题讨论】:

  • 旁注:add-to-listadd-to-ordered-list 只能用于保存在全局变量中的列表。 IOW 更改配置变量等内容。在所有其他情况下,您将需要使用 pushcl-pushnewconsnconcsetf、...。

标签: list sorting emacs


【解决方案1】:

你需要使用setcarnthcdr

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

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

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

【讨论】:

    【解决方案2】:

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

    (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,而第二次出现在列表中。

    【讨论】:

    • 非常感谢您帮助我理解为什么我在尝试使用列表中的变量时遇到了这么多麻烦。您提供的课程将来会派上用场! :)
    【解决方案3】:

    添加一个专门针对 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(而不是equalstring=)来区分它们。

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

    3. 为元素记录的顺序不需要为所有元素指定(见上文),它们不需要是连续的。重要的是它们可以进行数字比较,因此可以对它们的元素进行排序。例如,您可以添加元素 abc' to an empty list, recording orders of 13, 42, and 6 for them, respectively. The result is the list (c a b)`,因为 6

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

    另见this emacs.SE question

    【讨论】:

      猜你喜欢
      • 2020-01-10
      • 1970-01-01
      • 2011-08-27
      • 2021-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      相关资源
      最近更新 更多