Извлечение узлов образуют точечный список (ребра) в CLISP
Я "ноль" или () в мире Лисп.
Я хотел получить список всех узлов в списке краев и написал код для решения этой проблемы. Но я столкнулся с неожиданной проблемой.
(Коды из "Лиспской земли" - глава 8)
;; Creating edge list
(defun random-node ()
(1+ (random *node-num*)))
(defun edge-pair (a b)
(unless (eql a b)
(list (cons a b) (cons b a))))
(defun make-edge-list ()
(apply #'append (loop repeat *edge-num*
collect (edge-pair (random-node) (random-node)))))
(defparameter el (make-edge-list))
Я написал код для извлечения всего узла в виде списка, как показано ниже.
;; el : list of dotted list
;; I want to extract all the first element from every dotted lists in el.
;; el : ((25 . 6) (6 . 25) (2 . 13) (13 . 2) (25 . 16) (16 . 25) ....)
;; What I want to get: (25 6 2 13 25 16 ... )
(defun extract-nodes (el)
(let ((nodes nil))
(labels ((addNode (edgeList)
(push (caar edgeList) nodes)
(addNode (cdr edgeList))))
(addNode el))
nodes))
Я думал, что мой код был не так уж плох, но результат показал мне неловкое сообщение об ошибке.
"Stack overflow (deep)"
Переполнение стека? Я думаю, что это вызвано рекурсивной функцией в моем коде. Как я могу исправить это правильно?
Благодарю.
1 ответ
Решение
Ваш рекурсивный addNode
(лучше называть add-node
если ты шучу) нужно условие остановки. Например,
(add-node (edge-list)
(push (car (pop edge-list)) nodes)
(when edge-list
(add-node (cdr edge-list))))
Обратите внимание, что здесь нет причин использовать рекурсию, простой mapcar
будет хорошо
(defun extract-nodes (el)
(mapcar #'car el))