Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) 
;; "-------"

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?

like image 747
Baggers Avatar asked Nov 17 '14 10:11

Baggers


1 Answers

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).

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.

When the loop terminates, the result is the cdr of list-head.

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.

like image 112
Lars Brinkhoff Avatar answered Nov 18 '22 07:11

Lars Brinkhoff