2
\$\begingroup\$

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.

> (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 &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?

\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.