Pairwise grouping of elements of a list I want to group the elements in an arbitrary long list into pairs and implemented the following so far:

(defun group-pairwise (numbers)
  "Returns a list with the elements of NUMBERS grouped in pairs."
  (cond ((null numbers) nil)
        ((null (rest numbers)) nil)
        (t (append (list (list (first numbers) (second numbers)))
                   (group-pairwise (rest numbers))))))


It works, i.e.

&gt; (group-pairwise '(3 6 0))
((3 6) (6 0))


but I found (append (list (list (first numbers) (second numbers) a bit cumbersome. Is there any way to express it more elegant?

Furthermore, I want in my later code not only to return the list of pairs but to perform an action on each pair. To keep the recursion pattern unchanged I was thinking about using progn instead of append , e.g.

(defun generate-graph-of-digits%%% (numbers &amp;optional (graph *pe79-graph*))
  "Returns a graph structure of NUMBERS."
  (cond ((null numbers) nil)
        ((null (rest numbers)) nil)
        (t (progn
             (add-edge-between-vertexes graph (first numbers) (second numbers))
             (generate-graph-of-digits%%% (rest numbers))))))


add-edge-between-vertexes being defined in the cl-graph package.

I am unsure about the usage of progn. Is it recommended to use it here?
Much too complicated. Use MAPCAR:

(defun group-pairwise (numbers)
  "Returns a list with the elements of NUMBERS grouped in pairs."
  (mapcar #'list numbers (rest numbers)))


Similar:

(defun generate-graph-of-digits (numbers graph)
  (mapc (lambda (a b)
          (add-edge-between-vertexes graph a b))
        numbers
        (rest numbers)))


Such primitive recursion can be replaced with mapping functions. Bonus: mapping functions are not limited by recursion stack.

Style

Also:

(append (list (list a b)) some-list)


is

(cons (list a b) some-list)


Then:

(cond (a (progn b c d))
      ((evenp n) (progn o p q))
      (t (progn e f g)))


is:

(cond (a b c d)
      ((evenp n) o p q)
      (t e f g))


Each cond clause accepts any number of Lisp forms after the condition.