Я справді плутаю .
позначення. Чи '(a . b)
є список?
(listp '(a . b))
повертається, t
але коли я хочу знати, його довжина (length '(a . b))
видає помилку Wrong type argument: listp, b
. Те саме стосується інших функцій, як nth,mapcar
і т. Д. Всі вони дають однакову помилку
Чи є якась функція, яку я можу розрізняти '(a b)
і '(a . b)
?
Контекст: Я зіткнувся з цією проблемою, коли хотів реалізувати рекурсивну версію mapcar
. Ось моя реалізація
(defun true-listp (object)
"Return non-`nil' if OBJECT is a true list."
(and (listp object) (null (cdr (last object)))))
(defun recursive-mapcar (func list)
"Evaluates func on elements of the list, then on elements of elements of the list and so forth."
(let ((output nil))
(flet ((comp (a b) nil)
(call-fun-and-save (x) (add-to-list 'output (funcall func x) t 'comp))
(recursion (l)
(mapcar
(lambda (x)
(call-fun-and-save x)
(if (and (true-listp x)) ;; HERE I use true-listp, testing for list or cons is not sufficient
(recursion x)))
l)))
(recursion list))
output))
Я використовую це для вилучення всіх конкретних тегів з розбору HTML. Приклад html
розбору
;; buffer 'html'
<html>
<body>
<table style="width:100%">
<tr> <td>Jill</td> <td>Smith</td> <td>50</td> </tr>
<tr> <td>Eve</td> <td>Jackson</td> <td>94</td> </tr>
</table>
</body>
</html>
Тоді я витягую все <td>
як
(with-current-buffer (get-buffer "html")
(let ((data (libxml-parse-html-region (point-max) (point-min))))
;; gat only <td> tags
(-non-nil
(recursive-mapcar
(lambda(x) (and (consp x) (equal 'td (car x)) x))
data))
data
)
)
libxml-parse-html-region
і хочу витягнути всі <td>
теги.
consp
замість цього.
cddr
списком (щоб пропустити ім'я елемента та атрибути). Як тільки ви це зробите, ви повинні встановити, що всі списки є правильними і ваша проблема зникне. Він також виправить помилку у вашому коді, де ви можете заплутати td
атрибут для td
елемента.
true-list-p
Еліспі немає просто тому, що його не знайшли достатньо корисним для його надання. Дійсно, я не можу пригадати, коли я востаннє хотів перевірити, чи є список належним, тому, можливо, якщо ви дасте нам трохи більше інформації про ваше використання, ми можемо допомогти вам вирішити вашу проблему іншим способом.