意外的数据持久性

fpt*_*fpt 7 lisp scheme common-lisp literals

我有一个七个整数的列表,最初都是0,我们称之为"数据".在运行程序的过程中,我想定期将其中一个整数的值递增一.在程序结束时我打印数据.一切都很好,除了在程序的每次连续运行中,上次运行的所有数据值都被添加到此运行的所有数据值中.我只想要来自此次运行的数据值.无论数据是类的方法中的局部变量,类的方法调用的单独函数中的局部变量,还是类的槽,都会发生这种意外行为.无论我是通过incf还是(setf value(1+ value))递增数据的各个值,都会发生这种情况.当我重新加载程序时,数据重置为全零,但是当我再次运行程序时,数据会再次添加所有的最后一次运行' s数据到此运行的数据.当我增加其中一个数据值时,我使用函数nth,其中index是另一个对象槽的值.什么可能导致我的"数据"列表的值不受欢迎的持久性?

Jos*_*lor 17

你在做这样的事情:

CL-USER> (defun foo ()
           (let ((value '(1)))     ; '(1) is literal data
             (incf (car value))))
FOO
CL-USER> (foo)
2
CL-USER> (foo)
3
CL-USER> (foo)
4
CL-USER> (foo)
5
Run Code Online (Sandbox Code Playgroud)

引用的数据是文字数据; 它只有一个副本,修改它的后果是不确定的.上面的行为很常见,但你不能依赖它.有些编译器会在您执行此操作时发出警告.例如,在SBCL中:

CL-USER> (defun foo ()
           (let ((value '(1)))
             (incf (car value))))
; in: DEFUN FOO
;     (INCF (CAR VALUE))
; --> LET* 
; ==>
;   (SB-KERNEL:%RPLACA #:TMP1 #:NEW0)
; 
; caught WARNING:
;   Destructive function SB-KERNEL:%RPLACA called on constant data.
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3
; 
; compilation unit finished
;   caught 1 WARNING condition
FOO
Run Code Online (Sandbox Code Playgroud)

HyperSpec的相关文本quote是:

如果破坏性地修改文字对象(包括引用对象),则后果是不确定的.

创建可修改的列表,例如(list 1),不'(1).在你遇到它之前,这是一个常见的陷阱.StackOverflow上还有一些其他问题提到了这个问题.一个非常具体的是

但也有一堆:

在Scheme中也会发生同样的事情,尽管对文档的引用明显不同.对于R 5 RS,文档如下:

4.1.2文字表达

......如3.4节所述,使用像set-car这样的变异程序来改变常量(即文字表达式的值)是错误的!或字符串集!

3.4存储模型

...在许多系统中,希望常量(即文字表达式的值)驻留在只读存储器中.为了表达这一点,可以很方便地设想表示位置的每个对象都与一个标志相关联,该标志告诉该对象是可变的还是不可变的.在这样的系统中,文字常量和symbol-> string返回的字符串是不可变对象,而本报告中列出的其他过程创建的所有对象都是可变的.尝试将新值存储到由不可变对象表示的位置是错误的.

对此也存在疑问:


归档时间:

查看次数:

437 次

最近记录:

8 年,1 月 前