方案有定车!和 set-cdr!,但没有设置缺点!.
是表达式如
(设置!c(缺点 3 c))
哪个将元素 3 放在列表 c 上,修改列表的正确/唯一/最佳/通常方式?
(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)))))
这是修改列表 c 的正确方法。但这种用法很少见。也许你可以告诉我们更多关于你正在尝试做的事情。
您需要了解类型构造函数、修饰符和访问器。
对是用 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)
知道了?