2010-05-27 4 views
6

En SICP ejercicio 2.26, se da este código Esquema:En el ejercicio 2.26 del SICP usando DrScheme, ¿por qué se devuelve una lista en lugar de un par de listas?

(define x (list 1 2 3)) 
(define y (list 4 5 6)) 

entonces este contras llamada es dado:

(cons x y) 

que esperaba un par de listas daría como resultado, ((1 2 3) (4 5 6)) pero el intérprete da, ((1 2 3) 4 5 6) ... una lista con 4 elementos, el primero es una lista. ¿Por qué se trata de una manera diferente? Intenté buscar otras respuestas al SICP para obtener una explicación, pero no pude encontrar algo satisfactorio. Entonces, ¿podrían los expertos en Scheme/Lisp arrojar algo de luz sobre este aspecto de los contras? Gracias de antemano por cualquier información.

+1

Gracias a todos los que respondieron a mi pregunta, especialmente Nathan y tonio. Este novato en Scheme/Lisp ahora asimila el lenguaje un poco mejor debido a sus respuestas detalladas. – limist

+0

Ver también [Recu El rango de respuesta en Lisp agrega un punto?] (http://stackoverflow.com/q/16379657/1281433) para obtener una explicación similar. –

Respuesta

12

'((1 2 3) 4 5 6) es en realidad un par de listas. Aquí hay otra forma de escribirlo:

'((1 2 3) . (4 5 6)) 

Sin embargo, la impresora evita notación de pares de puntos siempre que puede, para que tenga lugar la primera representación. La regla es:

'(x . (xs ...)) 
=> 
'(x xs ...) 

Para cualquier x y xs. Aquí, su x = '(1 2 3) y xs = '(4 5 6), por lo que obtiene ((1 2 3) 4 5 6).


Para ver cómo los contras y notación par se relaciona, vamos a acortar el problema que acaba de '(1) y '(6). La manera más bajo nivel para construir un par de ellas es la siguiente:

(cons (cons 1 '()) (cons 6 '())) 

Aquí, '() es nula, o la lista vacía.Si traducimos esto literalmente a la notación de pares de puntos, obtenemos lo siguiente:

'((1 .()) . (6 .())) 

Pero debido a que la impresora se derrumba notación par siempre que sea posible, se obtiene de esta forma:

'((1 .()) . (6 .())) 
=> 
'((1) . (6)) ; <-- x=1, xs=nothing; x=6, xs=nothing 
=> 
'((1) 6) ; <-- x=1, xs=6 
+0

Gracias por la explicación detallada; Ahora veo que se trata de un par de listas, por el colapso de la notación de par de puntos, y desde (cdr (cons x y)) da la segunda lista. Pero ¿por qué (longitud (contras x y)) responde 4? ¿No debería ser 6 (contar todos los elementos de ambas listas) o 2 (contar dos listas)? – limist

+0

Ah, no importa mi comentario; Veo que es una consecuencia de la función (longitud) que dan en el libro que no trata con listas anidadas. – limist

+1

@limist: Bueno, más o menos. Su problema (creo) es pensar en List como un tipo de datos opaco e independiente. En realidad, es solo una convención de cómo usar pares de cons (ver la respuesta de tonio). Por lo tanto, para obtener la longitud 6, escribiría 'lista-anidada', aunque esto realmente se llamaría' tree-size' porque usa la convención del árbol para conses. Por otro lado, para obtener 2 de '(longitud (contras (1 2 3) '(4 5 6))', tendrías que obtener 2 para * cualquier * lista. Ese método ignora la convención de la lista que dice que, por ejemplo, '(1) es en realidad '(contra 1'())'. Su longitud es 1, no 2, debido a la forma en que se construyen las listas. –

10

cons usa el primer argumento como encabezado de la lista y el segundo como cola.

Le da una primera lista (1 2 3), que constituirá el encabezado de la lista resultante y una segunda lista (4 5 6), que se utilizará como la cola de la lista. Por lo tanto, terminas con ((1 2 3) 4 5 6).

Una cosa de listas como peines de izquierda a derecha, terminando con la lista vacía (representada como o aquí), y ver cómo se combinan.

X=  Y= 
/\  /\ 
1 /\ + 4 /\  
2 /\ 5 /\ 
    3 o 6 o 

A continuación, construye:

/\ 
X Y 

Obtención:

/\ 
/\ \ 
1 /\ \ 
2 /\ \ 
    3 o/\ 
    4 /\ 
     5 /\ 
     6 o 

que es ((1 2 3) 4 5 6 cuando se representa con paréntesis. Y este es un par de listas.

+0

Sí, traté de simplificar un poco el dibujo, pero eso no fue realmente un éxito. Intentaremos mejorar esto. – tonio

+0

Gracias por la explicación del diagrama, tiene sentido ahora. – limist

0

intento (lista x, y) Estoy seguro de que funciona en Common Lisp, no sé sobre el Esquema

1

hey, creo que se podría pensar de esta manera;

cada vez que hay un nulo, tiene que haber un par de paréntesis, de la siguiente manera:

(cons 1 (cons nil) 2) -> (1 Lista 2)

(let ((x (lista 1 2 3)) (y (lista 4 5 6))))

1. (cons xy) -> (contras (contras 1 (cons 2 (cons 3 nil))) (contras 4 (cons 5 (cons 6 nil)))) aquí, el primer nil representa el final de un par que podría expresarse mediante paréntesis; mientras que el segundo nil representa el final del par completo que usa otro par de paréntesis; así, ((1 2 3) 4 5 6)

2. (lista xy) -> (cons x (cons y nil); como sabemos los x contienen una nil, así que debe ser (1 2 3), la segunda parte contiene dos Nils, tan ((1 2 3) (4 5 6));

el interior más nil significa el más paréntesis exterior;.

esperan que los pueda ayudar

Cuestiones relacionadas