Я действительно запутался с .
обозначениями. Это '(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
Elisp его нет просто потому, что не было найдено, что оно достаточно полезно для его предоставления. Действительно, я не могу вспомнить, когда в последний раз я хотел проверить правильность списка, поэтому, возможно, если вы дадите нам немного больше информации о вашем сценарии использования, мы поможем решить вашу проблему другим способом.