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 次 |
| 最近记录: |