I can’t think why you wouldn’t use the Common Lisp loop macro in Emacs. Don’t forget to (require ‘cl-lib)
Simple Loops
;; keywords: to, upto, below, downto, above, by
;; keywords: collect, append, nconc, count, sum, maximize, minimize
(cl-loop
do (princ 1))
=> 111111... infinite loop
(cl-loop repeat 5
do (princ 1)
(princ 2))
=> 1212121212
(cl-loop for i from 1 below 10
maximize i)
=> 9
(cl-loop for x from 9 downto 1
collect x)
=> (9 8 7 6 5 4 3 2 1)
(cl-loop for i from 10 above 1 by 2
collect i)
=> (10 8 6 4 2)
Looping over Sets and Arrays
;; keywords: in, on, across, by
;; Remember in for lists
;; across for vectors
(cl-loop for l in '(1 2 3 4 5)
do (princ l))
=> 12345
(cl-loop for l in '(1 2 3 4 5) by #'cddr
collect l)
=> (1 3 5)
(cl-loop for l on '(1 2 3 4 5)
collect l)
=> ((1 2 3 4 5) (2 3 4 5) (3 4 5) (4 5) (5))
(cl-loop for l on '(1 2 3 4 5) by #'cddr
collect l)
=> ((1 2 3 4 5) (3 4 5) (5))
;; Remember that a string is an array in lisp, so...
;; Add up the digits in 90125
(cl-loop for d across "90125"
sum (- d 48))
=> 17
Destructuring
(cl-loop for (a nil) in '((1 2) (2 3) (3 4))
collect a)
=> (1 2 3)
(cl-loop for (a b) in '((1 2) (2 3) (3 4))
collect (* a b))
=> (2 6 12)
(cl-loop for (a b) on '(1 2 3 4 5) while b
collect (+ a b))
=> (3 5 7 9)
(cl-loop for (a b) on '(1 2 3 4 5) by #'cddr while b
collect (+ a b))
=> (3 7)
Hashtables
(cl-loop for key being the hash-keys of myhashtable
using (hash-value value)
do (princ value))
Parallel fors
(cl-loop for i from 1 to 5
for l in '(a b c d)
collect (list i l))
=> ((1 a) (2 b) (3 c) (4 d))
(cl-loop for i from 1 to 5
for j from 2 to 10 by 2
collect (* i j))
=> (2 8 18 32 50)
Nested fors
(cl-loop for i from 1 to 5
collect (cl-loop for j from 1 to 5
collect (* i j)))
=> ((1 2 3 4 5) (2 4 6 8 10) (3 6 9 12 15) (4 8 12 16 20) (5 10 15 20 25))
(cl-loop for i from 1 to 5
append (cl-loop for j from 1 to 5
collect (* i j)))
=> (1 2 3 4 5 2 4 6 8 10 3 6 ...)
(cl-loop for i from 1 to 5
collect (cl-loop for j from 1 to 5
sum (* i j)))
=> (15 30 45 60 75)
(cl-loop for i from 1 to 5
sum (cl-loop for j from 1 to 5
sum (* i j)))
=> 225
Selection
;; if, when, unless
(cl-loop for i from 1 to 20
unless (cl-evenp i) collect i)
=> (1 3 5 7 9 11 13 15 17 19)
(cl-loop for i from 1 to 20
when (= (% i 3) 0) collect i into fizz
when (= (% i 5) 0) collect i into buzz
finally return (list fizz buzz))
=> ((3 6 9 12 15 18) (5 10 15 20))
(cl-loop for i from 1 to 20
if (and (= (% i 3) 0) (= (% i 5) 0)) collect i into fizzbuzz
else if (= (% i 3) 0) collect i into fizz
else if (= (% i 5) 0) collect i into buzz
finally return (list fizz buzz fizzbuzz))
=> ((3 6 9 12 18) (5 10 20) (15))
(cl-loop for i from 1 to 10
if (cl-evenp i)
collect i into evens
and sum i into evensum
else
collect i into odds
and sum i into oddsum
finally return (list evens evensum odds oddsum))
=> ((2 4 6 8 10) 30 (1 3 5 7 9) 25)
Find c from comp where diff is never a member of squares
(cl-loop for c in comp
if (cl-loop for p in pri
for diff = (/ (- c p) 2)
never (member diff squares))
collect c)
Then Iteration
(cl-loop for i from 1 to 5
for square = (* i i)
collect square)
;; Though you'd be better with
(cl-loop for i from 1 to 5
collect (* i i))
;; However, this leads to Triangle Numbers
(cl-loop for n from 1 to 10
for triangle = 1 then (+ triangle n)
collect triangle)
=> (1 3 6 10 15 21 28 36 45 55)
(cl-loop for x = 0 then y
for y = 1 then (+ x y)
while (< y 30)
collect y)
=> (1 2 4 8 16)
;; Fibonacci Sequence (note the and)
(cl-loop for x = 0 then y
and y = 1 then (+ x y)
while (< y 30)
collect y)
=> (1 1 2 3 5 8 13 21)
Termination
;; while, until, always, never, and thereis
while and until are straightforward
(cl-loop for n from 1
for tri = 1 then (+ tri n)
until (> (divs tri) 500)
finally return tri)
never, thereis and always are shorthand for a combination of when-return
(defun isprime(n)
(cond
((< n 2) nil)
((= n 2) t)
((cl-evenp n) nil)
(t
(cl-loop for i from 3 to (sqrt n) by 2
never (= (% n i) 0)))))