Estoy realmente confundido con la .notación. Es '(a . b)una lista?
(listp '(a . b))vuelve tpero cuando quiero saber su longitud (length '(a . b))da un error Wrong type argument: listp, b. Lo mismo es para otras funciones como nth,mapcaretc. todos dan el mismo error
¿Hay alguna función que pueda distinguir entre '(a b)y '(a . b)?
Contexto: Encontré este problema cuando quería implementar la versión recursiva de mapcar. Aquí está mi implementación
(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 para extraer todas las etiquetas específicas del html analizado. Ejemplo de htmlanalizar
;; 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>
Luego extraigo todo <td>como
(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
)
)

true-list-pen Elisp simplemente porque no se ha encontrado que sea lo suficientemente útil como para proporcionarlo. De hecho, no recuerdo la última vez que quise probar si una lista era correcta, así que tal vez si nos brinda un poco más de información sobre su caso de uso, podemos ayudarlo a resolver su problema de otra manera.libxml-parse-html-regiony deseo extraer todas las<td>etiquetas.consplugar.cddrla lista (para omitir el nombre del elemento y los atributos). Una vez que haga eso, debería encontrar que todas las listas son correctas y su problema desaparecerá. También solucionará un error en su código donde puede confundir untdatributo de untdelemento.Respuestas:
Satisface
listp, así que en ese sentido es una lista.listpsolo prueba si algo es una desventaja onil(aka()), por un lado, o algo más, por otro lado.Una lista adecuada o una lista verdadera (o una lista que no es una lista punteada o una lista circular) es algo que es
listpy también tienenilcomo su último cdr. Es decir, una listaXSes adecuada si(cdr (last XS))es asínil(y así es como la distingue).Otra forma de decir esto es que una lista adecuada tiene una lista adecuada como su cdr . Esta es la forma en que la Lista de tipos de datos (adecuada) se define en los idiomas escritos. Es una definición de tipo genérico y recursivo: la parte genérica dice que el primer argumento para el constructor de lista no vacía (a menudo llamado
cons, por cierto) puede ser de cualquier tipo. La parte recursiva dice que su segundo argumento es una instancia de tipo (apropiado) Lista .Sí, verifica si un dado
listpes una lista adecuada usando(cdr (last XS))isnil. Para verificar si el cdr del bicho es en sí mismo una lista adecuada, debe continuar verificando su cdr, hasta el final, los últimos inconvenientes, para ver si es asínil. Puede definir un predicado para esto de la siguiente manera, si desea:Aunque una lista circular no tiene fin, Emacs (comenzando con Emacs 24) es lo suficientemente inteligente como para verificar
lastcorrectamente, por lo que este código funciona incluso para una lista circular (pero solo para Emacs 24.1 y posterior; para versiones anteriores obtienes una recursión "infinita" hasta que la pila se desborde).Puede usar funciones como
lengthsolo en listas apropiadas y otras secuencias. Ver también funciónsafe-length.Consulte el manual de Elisp, celdas de cons . De nodo .
En cuanto a la notación,
(a b)es solo azúcar sintáctica para(a . (b . nil))- vea el manual de Elisp, notación de pares de puntos de nodofuente
(cdr (last XS))esniles crumblesome. ¿No hay una función comoproper-list-p?(unless (atom x) (not (cdr (last x))))Para que puedas llamar(true-list-p "text")ynilno obtener un error.nil(es decir,listp). (Además, pedía algo, yo no usounlessowhenpor su valor de retorno que utilizo.and,orY,ifpor eso.)