表达式如(set!c(cons 3 c))是否可以将项目添加到列表中?

drb*_*drb 2 scheme cons

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

是表达式如

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

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

Lui*_*las 5

(set! c (cons 3 c))

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

  • set!将变量作为其第一个参数,将表达式作为第二个参数.它计算第二个参数,并将值赋给变量.
  • cons 获取一个值和一个列表,并生成一个列表,其中给定值作为其头部,给定列表作为其尾部.

因此,(set! c (cons 3 c))构造一个包含3head和ctail的列表,并将该列表指定为值c.此更改仅对访问相同绑定的代码可见c- 如果有其他变量或引用原始列表的对象字段,则它们仍引用该原始列表.

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

我可以立即想到两个主要的事情,也可以算作"将项目添加到列表中":

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

第一个例子:

(define (insert-at-second-position! item list)
  (set-cdr! list (cons item (cdr list))))
Run Code Online (Sandbox Code Playgroud)

第二个例子:

(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)))))
Run Code Online (Sandbox Code Playgroud)