¿Es '(a. B) realmente una lista?

Pregunta:

Estoy realmente confundido con . notación. ¿Es '(a . b) una lista?

(listp '(a . b)) devuelve t pero cuando quiero saber su longitud (length '(a . b)) da un error Wrong type argument: listp, b . Lo mismo nth,mapcar con otras funciones como nth,mapcar etc., todas dan el mismo error

¿Existe alguna función que pueda distinguir entre '(ab) y '(a . b) ?


Contexto: encontré este problema cuando quise 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))

Utilizo esto para extraer todas las etiquetas específicas de html analizado. Ejemplo de html para analizar

;; 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
    )
  )

Respuesta:

Satisface listp , por lo que en ese sentido es una lista. listp solo prueba si algo es un contra o nil (también conocido como () ), 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 de puntos o una lista circular) es algo que es listp y también tiene nil como su último cdr. Es decir, una lista XS es adecuada si (cdr (last XS)) es nil (y así es como se distingue).

Otra forma de decirlo es que una lista adecuada tiene una lista adecuada como su cdr . Esta es la forma en que se define la lista de tipos de datos (propiamente dichos) en los lenguajes escritos. Es una definición de tipo genérica y recursiva: la parte genérica dice que el primer argumento del constructor de listas no vacías (a menudo llamado cons , BTW) puede ser de cualquier tipo. La parte recursiva dice que su segundo argumento es una instancia del tipo (propiamente dicho) List .

Sí, se comprueba si un determinado listp es una lista adecuada usando (cdr (last XS)) es nil . Para verificar si el cdr de la criatura es en sí mismo una lista adecuada, debe continuar verificando su cdr, hasta el final, las últimas desventajas, para ver si es nil . Puede definir un predicado para esto de la siguiente manera, si quisiera:

(defun true-listp (object)
  "Return non-`nil' if OBJECT is a true list."
  (and (listp object)  (null (cdr (last object)))))

Aunque una lista circular no tiene fin, Emacs (comenzando con Emacs 24) es lo suficientemente inteligente como para verificar el last correctamente, por lo que este código funciona incluso para una lista circular (pero solo para Emacs 24.1 y posteriores; para versiones anteriores, obtiene un "infinito" recursividad hasta desbordamiento de pila).

Puede usar funciones como la length solo en listas adecuadas y otras secuencias. Consulte también función safe-length .

Consulte el manual de Elisp, nodo Cons Cells .

En cuanto a la notación, (ab) es solo azúcar sintáctico para (a . (b . nil)) Nil (a . (b . nil)) ; consulte el manual de Elisp, nodo Dotted Pair Notation

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım