2

方案有定车!和 set-cdr!,但没有设置缺点!.

是表达式如

(设置!c(缺点 3 c))

哪个将元素 3 放在列表 c 上,修改列表的正确/唯一/最佳/通常方式?

4

3 回答 3

5

(set! c (cons 3 c))

好吧,让我们弄清楚这个表达式的作用:

  • set!将变量作为第一个参数,将表达式作为第二个参数。它评估第二个参数,并将值分配给变量。
  • cons接受一个值和一个列表,并生成一个以给定值作为头部,给定列表作为尾部的列表。

因此,(set! c (cons 3 c))构造一个3作为头部和c尾部的列表,并将该列表分配为 的值c。此更改仅对访问相同绑定的代码可见c- 如果有其他变量或对象字段引用原始列表,它们仍然引用该原始列表。

在某些情况下,这可以松散地描述为“将项目添加到列表” ,但这是一个松散的描述,因为您没有获取现有列表并将其修改为具有新项目;相反,您正在创建一个列表,其中包含一个新的初始项目和原始列表作为其尾部,并更改对旧列表的一些(但可能不是全部)引用以指向新列表。

我可以立即想到两件主要的事情,这也可以算作“将项目添加到列表”:

  • 修改现有列表的结构以在中间或末尾的某处添加新的对。如果您对术语非常严格,那么这是“将项目添加到列表”的唯一真实情况。
  • 将一个项目放在列表的前面并将其返回给调用者或将其作为参数传递给另一个函数(没有设置!)。这是比您的示例更宽松的语言 - 但它也是最常见的情况!

第一个例子:

(define (insert-at-second-position! item list)
  (set-cdr! list (cons item (cdr list))))

第二个例子:

(define (list-copy xs)
  (if (null? xs)
      '()
      ;; We call list-copy recursively on the tail, and "add an item"
      ;; at the front:
      (cons (car xs)
            (list-copy (cdr xs)))))
于 2012-01-23T19:31:26.323 回答
1

这是修改列表 c 的正确方法。但这种用法很少见。也许你可以告诉我们更多关于你正在尝试做的事情。

于 2012-01-23T16:35:42.487 回答
0

您需要了解类型构造函数、修饰符和访问器。

对是用 cons 构造的,它是一个有 2 个参数的过程,第一个参数(汽车)是对的第一个元素,第二个参数(cdr)是对的第二个元素。正确的列表要求它的 cdr 是一个以 null 结尾的列表。否则,它只是一对。

对选择器(car 和 cdr)采用一个参数,一个 CONStructed 列表,并提取第一个(使用 car)或其余(使用 cdr)是对参数。

修饰符(setter)接受 2 个参数:一个现有的 CONStruct(一对,一对汽车,基本上任何已构造的东西),并用其第二个参数的值替换选定的构造。

(set-car! (cons 'a (cons 'b '())) 'c) ;; is the same as
(set! (car (cons 'a (cons 'b '()))) 'c)

知道了?

于 2012-01-28T17:37:00.837 回答