eintr: Keep

 
 Recursive Pattern: _keep_
 .........................
 
 A third recursive pattern is called the ‘keep’ pattern.  In the ‘keep’
 recursive pattern, each element of a list is tested; the element is
 acted on and the results are kept only if the element meets a criterion.
 
    Again, this is very like the ‘every’ pattern, except the element is
 skipped unless it meets a criterion.
 
    The pattern has three parts:
 
    • If a list be empty, return ‘nil’.
    • Else, if the beginning of the list (the CAR of the list) passes a
      test
         − act on that element and combine it, using ‘cons’ with
         − a recursive call by the function on the rest (the CDR) of the
           list.
    • Otherwise, if the beginning of the list (the CAR of the list) fails
      the test
         − skip on that element,
         − and, recursively call the function on the rest (the CDR) of
           the list.
 
    Here is an example that uses ‘cond’:
 
      (defun keep-three-letter-words (word-list)
        "Keep three letter words in WORD-LIST."
        (cond
         ;; First do-again-test: stop-condition
         ((not word-list) nil)
 
         ;; Second do-again-test: when to act
         ((eq 3 (length (symbol-name (car word-list))))
          ;; combine acted-on element with recursive call on shorter list
          (cons (car word-list) (keep-three-letter-words (cdr word-list))))
 
         ;; Third do-again-test: when to skip element;
         ;;   recursively call shorter list with next-step expression
         (t (keep-three-letter-words (cdr word-list)))))
 
      (keep-three-letter-words '(one two three four five six))
          ⇒ (one two six)
 
    It goes without saying that you need not use ‘nil’ as the test for
 when to stop; and you can, of course, combine these patterns.