## Do Forms

### do ((var [start [step]])*) (stop result*) form* ⇒ result*

Iterate over a group of statements while a test condition holds. Variables are bound within the iteration and stepped in parallel.

Using do* causes the variable bindings and steppings to be performed sequentially rather than in parallel.

``````(do ((i 0 (1+ i)))              ;init to 0, step 1
((>= i 4) (print 'done))    ;end test, result-form
(print i))                    ;⇒ NIL [prints 0..3, done]

(do ((n 0 (1+ n))               ;init to 0, step 1
(current 0 next)           ;init to 0, read old value of next
(next 1 (+ current next))) ;init to 1, reads old values
((= 10 n) current))         ;⇒ 55 end test and result-form

(do ()
((> (get-universal-time) *some-future-date*))
(print "waiting...")
(sleep 60))``````

### dotimes (var i [result]) form* ⇒ result*

Iterate over a series of integers. Terminate loop immediately with return.

``````(dotimes (i 10)
(print i))

(dotimes (i 10 (print 'done))
(print i))``````

## Map/Reduce/Filter

### dolist (var list [result]) form* ⇒ result*

Iterate over the elements of a list. Terminate loop immediately with return.

``````(dolist (x '(1 2 3 4))
(print x))

(dolist (x '(1 2 3 4) (print 'done))
(print x))``````

### mapcar

Iterates over successive list elements and returns the accumlated results. mapc is similar except the results are not accumulated and the first list is returned.

``````(mapcar #'+ '(1 2) '(3 4)) ;⇒ (4 6)
(mapcar (alexandria:compose #'print #'1+) '(1 2 3)) ;⇒ (2 3 4) [prints 2,3,4]``````

### alexandria:mappend fn &rest lists… ⇒ list

Zips up list components and returns a flattened list. fn must return a list.

``````(mappend #'list '(1 3) '(2 4)) ;⇒ ((1 2) (3 4)) ⇒ (1 2 3 4)

(flet ((zipper (x y) (list (+ x y))))
(mappend #'zipper '(1 3) '(2 4))) ;⇒ ((+ 1 2) (+ 3 4)) ⇒ (3 7)``````

### alexandria:map-product fn list &rest lists… ⇒ list

Results of calling `fn` with one argument per list for every combination.

``````(map-product #'list '(1 2) '(3 4) '(5 6))
;⇒ ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))``````

### map result-type fn &rest seqs* ⇒ result

Applies the function to elements of each sequence in turn. The result sequence is as long as the shortest of the sequences.

``````(map 'list #'cons '(a b) '(c d))              ;⇒ ((A . C) (B . D))
(map 'vector #'(lambda (x) (* 2 x)) '(1 2 3)) ;⇒ #(2 4 6)``````

### map-into result-seq fn &rest seqs* ⇒ result-seq

Destructively modifies result-seq to contain the results of applying the function to each element in the argument seqs in turn.

``(map-into '(a b c) #'oddp '(1 2 3 4 5 6)) ;⇒ (T NIL T)``

### remove-if-not fn seq &key from-end start end count key ⇒ seq

Filter

``````(remove-if-not #'oddp '(0 1 2 3 4)) ;⇒ (1 3)
(remove-if-not (alexandria:disjoin #'zerop #'oddp) '(0 1 2 3 4)) ;⇒ (0 1 3)``````

### remove-if fn seq &key from-end start end count key ⇒ seq

``````(remove-if #'oddp '(0 1 2 3 4)) ;⇒ (0 2 4)
(remove-if (alexandria:disjoin #'zerop #'oddp) '(0 1 2 3 4)) ;⇒ (2 4)``````

### reduce fn seq &key key from-end start end initial-value ⇒ result

``(reduce #'* '(1 2 3 4 5)) ;⇒ 120``

## Hash-Tables

### maphash function hash-table ⇒ nil

Iterate over hash-table entries, calling function with two arguments, the key and value of that entry.

``````(setf ht (alexandria:plist-hash-table '(:x 10 :y 20))
buf (list))
(maphash #'(lambda (key val)
(push (list key val) buf)) ht)            ;⇒ NIL
buf                                                    ;⇒ ((:Y 20) (:X 10))``````

### alexandria:maphash-keys function hash-table ⇒ nil

Like maphash, but calls function with each key in the hash-table.

``````(setf buf (list))
(alexandria:maphash-keys #'(lambda (key)
(push key buf)) ht) ;⇒ NIL
buf                                              ;⇒ (:Y :X)``````

### alexandria:maphash-values function hash-table ⇒ nil

Like maphash, but calls function with each value in the hash-table.

``````(setf buf (list))
(alexandria:maphash-values #'(lambda (val)
(push val buf)) ht) ;⇒ NIL
buf                                                ;⇒ (20 10)``````

### loop for [key|value] being the [hash-keys|hash-values] in hash-table

Using the extended form of loop, iterate over hash-table entries binding to key and value.

``````(loop
for key being the hash-keys in ht
for val being the hash-values in ht
collect (list key val))             ;⇒ ((:X 10) (:Y 20))``````

### iterate for (key value) in-hashtable hash-table

Using the iterate package, iterate over hash-table entries binding to key and value.

``````(iter (for (key val) in-hashtable ht)
(collect (list key val)))           ;⇒ ((:X 10) (:Y 20))``````

## Recursion

Tesing if a list contains an element using tail-recursion:

``````(defun our-member (obj lst)
(if (null lst)                    ;finished if empty list, return nil
nil
(if (eql (car lst) obj)         ;if obj is first list element, return list
lst
(our-member obj (cdr lst))))) ;else, test against rest of list``````

Using an accumulator:

``````(defun fac (x)
(labels ((fac2 (x acc)          ;function takes current step and accumulated results
(if (= x 0)
acc                         ;if done, return accumulated results list
(fac2 (- x 1) (* acc x))))) ;else, call again with stepped down arg and accumulation
(fac2 x 1)))                  ;initial call to start``````