【发布时间】:2014-11-17 10:00:19
【问题描述】:
我扩展了下面的宏,看看它是如何工作的,发现自己有点困惑。
(loop for i below 4 collect i)
扩展为(为了便于阅读,我已经对其进行了一些清理)
(block nil
(let ((i 0))
(declare (type (and number real) i))
(let* ((list-head (list nil))
(list-tail list-head))
(tagbody
sb-loop::next-loop
(when (>= i 4) (go sb-loop::end-loop))
(rplacd list-tail (setq list-tail (list i)))
(setq i (1+ i))
(print "-------") ;; added so I could see the lists grow
(print list-head)
(print list-tail)
(print "-------")
(go sb-loop::next-loop)
sb-loop::end-loop
(return-from nil (cdr list-head))))))
..这是运行上面的输出..
;; "-------"
;; (NIL 0)
;; (0)
;; "-------"
;; "-------"
;; (NIL 0 1)
;; (1)
;; "-------"
;; "-------"
;; (NIL 0 1 2)
;; (2)
;; "-------"
;; "-------"
;; (NIL 0 1 2 3)
;; (3)
;; "-------"
我只是看不到 list-head 的修改位置,我必须假设 head 和 tail 是 eq ,因此修改一个正在修改另一个,但有人可以分解rplacd 行上发生的事情?
【问题讨论】:
-
为什么要修改列表头?将其视为单个链表:头部不会改变,只有尾部会在添加新元素时改变。但是,应用于列表的
print函数会打印从当前元素到最后一个元素的列表,这就是为什么您会看到列表头在增长而列表尾发生变化的原因。 -
我不想修改它。我想了解实际发生的情况。如果打印输出使情况混乱,那么这可能就是我不理解的原因。您应该在答案中发表评论,以便我可以按您的方式发送业力!
-
+1 用于挖掘源代码、使用宏扩展、显示有问题的明确行为等的好问题。很好!
-
又名“头哨把戏”。
标签: loops macros common-lisp