Использовать стандартное форматирование.См., Например, Practical Common Lisp .
(defun grouper1 (l1 l2)
(setq l (list (car l1) (car l2))) ; initialization of symbol 'l'
(loop
(setq l1 (cdr l1))
(when (null (car l1)) (return l))
(setq l2 (cdr l2))
(setq l (append l (list (car l1) (car l2))))))
Вопреки тому, что вы, похоже, подразумеваете под своим комментарием, setq
не указано для инициализации переменной.Используйте let
, чтобы ввести локальные переменные.
(defun grouper1 (l1 l2)
(let ((l (list (car l1) (car l2))))
(loop
(setf l1 (cdr l1))
(when (null (car l1)) (return l))
(setf l2 (cdr l2))
(setf l (append l (list (car l1) (car l2)))))))))
Ваша проблема в том, что вы append
частичные списки, т.е. составляете один список из них.(append (list 1 2) (list 3 4))
- это (1 2 3 4)
.Вместо этого вы должны собрать их.Другая проблема с append
заключается в том, что он неэффективен в цикле, потому что вы создаете квадратичное время выполнения для по существу линейной операции.Полезная идиома, когда вы делаете это «вручную», это использование push
и nreverse
.Наконец, вы всегда создаете первую пару, даже если первый список ввода был пустым.Вы должны собирать данные только в цикле, а не во время инициализации.
(defun grouper1 (l1 l2)
(let ((l ()))
(loop
(when (endp l1)
(return (nreverse l)))
(push (list (car l1) (car l2)) l)
(setf l1 (cdr l1)
l2 (cdr l2)))))
Что должно произойти, если l2
пусто?Если он также должен завершиться, то вы также можете использовать расширенную конструкцию цикла, чтобы помочь с управлением списком:
(defun grouper1 (l1 l2)
(loop :for x1 :in l1
:and x2 :in l2
:collect (list x1 x2)))
Или вы можете просто использовать mapcar
:
(defun grouper1 (l1 l2)
(mapcar #'list l1 l2))
Если вы на самом деле хотите завершить работу только тогда, когда l1
подходит к концу, и набрать nil
s, когда l2
короче, вам нужно добавить заполнение для этих двух последних решений.