(defclass schedule ()
((day :accessor schedule-day :initarg :day)))
(setf october
(make-array '(31)
:element-type 'schedule
:initial-element
(make-instance 'schedule :day 0)))
(setq searcher (read))
(setf (schedule-day (aref october (- searcher 1))) searcher)
(dotimes (i 31)
(format t "-month:10 day:~S~%" (schedule-day (aref october i))))
这是我的十月调度计划的一部分。 这部分应该是我输入的那一天,并更改当天的元素,并打印每个十月的时间表。
然而,
(setq searcher (read))
(setf (schedule-day (aref october (- searcher 1))) searcher)
我遇到了麻烦。如果我输入17,那么只有october
的第17天会受到影响并打印出来,
-month:10 day:0
-month:10 day:0
...
-month:10 day:17
-month:10 day:0
...
但我真正得到的是
-month:10 day:17
-month:10 day:17
-month:10 day:17
...
为什么我不能只改变一个元素?我设法用c ++这样做,
october[searcher - 1].setDay(searcher);
似乎setf
影响类本身,而不影响类对象。你能帮助我吗?谢谢。
答案 0 :(得分:6)
您的问题是您的数组包含31个指针,每个指针指向同一个对象。
因此(setf (schedule-day (aref october a)) b)
修改了该唯一对象。
您可以通过封装october
来实现所需的目的,以便仅在必要时创建i
元素,或者通过使用类似
(apply #'vector (loop repeat 31 collect (make-instance 'schedule)))
或
(make-array 31 :initial-contents (loop repeat 31 collect (make-instance 'schedule)))
您混淆的根本原因是您指定了数组元素类型并假设您创建了"specialized" array。
因此,尽管您实际上只调用(make-instance 'schedule)
一次,但在连续内存中将有31个对象。
但是,您的实施不有义务兑现
中方式的元素类型规范(它将创建一个数组
可以保存您指定类型的对象,但不一定
仅那些对象),
你实际得到的是simple-vector
。
PS。你应该
使用defvar
or defparameter
而不是setq
或setf
来定义全局
变量(如october
),你应该命名它们
运用
"earmuffs",
比如*october*
。
答案 1 :(得分:4)
您可以很容易地看到数组元素只指向一个CLOS对象。
CL-USER 28 > (defclass foo () ())
#<STANDARD-CLASS FOO 4020002613>
CL-USER 29 > (make-array 3 :initial-element (make-instance 'foo))
#(#<FOO 402000AE9B> #<FOO 402000AE9B> #<FOO 402000AE9B>)
所有对象都具有相同的ID 402000AE9B
。
在下一个示例中,对象是不同的:
CL-USER 30 > (make-array 3 :initial-contents (list (make-instance 'foo)
(make-instance 'foo)
(make-instance 'foo)))
#(#<FOO 4020000B43> #<FOO 4020000B63> #<FOO 4020000B83>)
所有ID都不同。