Sono davvero confuso con la .
notazione. È '(a . b)
un elenco?
(listp '(a . b))
ritorna t
ma quando voglio sapere la sua lunghezza (length '(a . b))
dà un errore Wrong type argument: listp, b
. Lo stesso vale per altre funzioni, nth,mapcar
ecc. Danno tutte lo stesso errore
C'è qualche funzione che posso distinguere tra '(a b)
e '(a . b)
?
Contesto: ho riscontrato questo problema quando volevo implementare la versione ricorsiva di mapcar
. Ecco la mia implementazione
(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))
Lo uso per estrarre tutti i tag specifici da HTML analizzato. Esempio di html
analisi
;; 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>
Quindi estraggo tutto <td>
come
(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
e voglio estrarre tutti i <td>
tag.
consp
invece.
cddr
quello dell'elenco (per saltare il nome dell'elemento e gli attributi). Una volta fatto ciò, dovresti scoprire che tutti gli elenchi sono corretti e il tuo problema scomparirà. Risolverà anche un bug nel tuo codice in cui potresti confondere un td
attributo per un td
elemento.
true-list-p
in Elisp semplicemente perché non è stato trovato abbastanza utile per fornirlo. In effetti, non ricordo l'ultima volta che ho voluto verificare se un elenco fosse corretto, quindi forse se ci dai un po 'più di informazioni sul tuo caso d'uso, possiamo aiutarti a risolvere il tuo problema in un altro modo.