了解循环宏扩展 [英] Understanding loop macro expansion
问题描述
我在下面扩展了宏,以查看其工作原理,并发现自己有些困惑.
I expanded the macro below to see how it worked and found myself a little confused.
(loop for i below 4 collect i)
扩展到(为了便于阅读,我对其进行了一些清理)
expands to (I have cleaned it up a little for readability)
(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))))))
..这是运行上述命令的结果.
..and here is the output from running the above..
;; "-------"
;; (NIL 0)
;; (0)
;; "-------"
;; "-------"
;; (NIL 0 1)
;; (1)
;; "-------"
;; "-------"
;; (NIL 0 1 2)
;; (2)
;; "-------"
;; "-------"
;; (NIL 0 1 2 3)
;; (3)
;; "-------"
我只是看不到列表头在哪里修改,我不得不假设头和尾是eq
,因此修改一个就是在修改另一个,但是有人可以分解一下rplacd
行上发生的事情?
I just can't see where list-head is modified, I have to assume head and tail are eq
and thus modifying one is modifying the other but could someone please break down what is happening on the rplacd
line?
推荐答案
list-head
和list-tail
最初是 相同 (在eq
意义上). list-head
是一个缺点,cdr是要收集的列表. list-tail
指向列表中的最后一个弊端(最初除外,请参见下文).
list-head
and list-tail
are initially the same (in the eq
sense). list-head
is a cons which cdr is the list being collected. list-tail
points to the last cons in the list (except initially, see below).
要将元素添加到列表的末尾,replacd
修改list-tail
的cdr以添加新的缺点,并且list-tail
被更新以指向新的缺点.
To add an element to the end of the list, replacd
modifies the cdr of list-tail
to add a new cons, and list-tail
is updated to point to the new cons.
当循环终止时,结果为list-head
的cdr.
When the loop terminates, the result is the cdr of list-head
.
为什么这项复杂的业务有额外的弊端?因为当list-tail
始终是指向列表的最后一个缺点的指针时,列表附加算法变得更加容易.但一开始,空列表没有缺点.因此,诀窍是使列表变长一些.
Why this complicated business with an extra cons? Because the list appending algorithm becomes easier when list-tail
is always a pointer to the last cons of the list. But in the beginning, the empty list has no cons. So the trick is to make the list one cons longer.
这篇关于了解循环宏扩展的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!