Scheme中列表(或其他)的副本

 Duanzd09 发布于 2023-02-07 19:49

我是Scheme的新手,发现如果我用set-car更改列表!/ set-cdr!(甚至在本地)父类列表也被修改.这就是我的意思:

(define my-list '(1 2 3 4 5)) ; Original list

(define (function list) ; Some example function
   (let ((copy list))
        (set-car! copy 'new)
   (display copy)
)

(function my-list); will display (new 2 3 4 5)

my-list; but the original is changed "forever" and will be also '(new 2 3 4 5)


我的问题是: 有没有办法制作原始列表的副本,只能在它上面工作,所以最后原来不能改变?

1 个回答
  • 您的代码(let ((copy list))允许通过名称副本访问列表.因此,当您set-car!复制时,您实际上是set-car!在原始列表中.

    lisp语言中的突变现象起初有点令人困惑.

    由于您发现的原因,通常应避免突变.列表和事物的一部分浮动.这是因为列表中的每个节点内部都有两个部分 - car它的值可能指向另一个列表,而它cdr是跟随它的部分 - 通常这是一个类似于值的内容car.

    这解决了使用SRFI1的列表复制功能的问题(let((copy(list-copy list)))

    这是复制列表的一种方法(制作新列表).这段代码并不完整.当我们在内部查看它时,它会在每个递归调用中添加一个列表的片段.每个新列表部分的部分来自哪里?通过cdr调用生成(list-copy (cdr list)),而car只是采取 - 不复制! - 从另一个清单.

    (define (list-copy list)
      (if (null? list) '() (cons (car list) (list-copy (cdr list)))))
    

    你在试验时得到的结果就是copy从你的名单借来的汽车my-list.

    这是一个更合适的版本:

    (define (full-copy list)
    (if (null? list) 
      '() 
      (if (list? list) 
          (cons (full-copy (car list)) (full-copy (cdr list)))
          list)))
    

    只有代码car已更改.现在,汽车被重建为.借用的唯一部分是数字(因此,当数字更为特殊时,此副本不合适).我不确定srfi1版本是如何工作的.

    let语句只会将一个标识符绑定到一个对象 - 该对象不会被复制,您只需要另一种方法来访问它.所以任何变化(使用变异,如在以"!"结尾的函数中)都将影响两者.

    2023-02-07 19:51 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有