Iteration

High Level Overview

  • 2 rules:
    • respect the order
    • don't nest accumulating clauses

;; Initialize variables we loop over
:for x :in '(1 3 5)
:for i :from 1 :to 2 ;; ranges: to, belown, downto...
:for y := i :then 99

;; use intermediate variables
:with z := "z" ;; set once, not iterated.

;; initial clause
:initially (format t "initially, i = ~S" i)

;; Body.
;; Conditionals: if/else, when,
;; while, until, repeat
:if (> i 99)
:do (return i)  ;; early exit

;; Main clauses: ;; do, collect... into,
;; count, sum, maximize
;; thereis, always, never
:sum x :into res

;; Final clause, called last before exit
:finally (return (list i res))

  • I want to nest accumulating clauses
    • see iterate, it doesn't have these limitations
    • see uiop:with-collecting or the collectors library

;; loop smells
(loop for i to 10
    do (if (> i 3)
;;      ^^ smell
            (collect i)))
;;            ^^ bad place

;; correction:
(loop for i to 10
    if (> i 3)
    collect i)


(let ((res '()))
    (loop for i upto 10
        if (> i 5)
        do (push i res))
    (reverse res))

;; correction:
(loop for i upto 10
    if (> i 5)
    collect i)