2010-05-27 8 views
6

In SICP esercizio 2.26, è dato questo codice Scheme:Nell'esercizio SICP 2.26 che utilizza DrScheme, perché viene restituito un elenco anziché una coppia di elenchi?

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

Poi questo cons chiamata è dato:

(cons x y) 

mi aspettavo un paio di liste comporterebbe, ((1 2 3) (4 5 6)) ma l'interprete dà, ((1 2 3) 4 5 6) ... un elenco con 4 elementi, il primo è un elenco. Perché viene trattato diversamente? Ho provato a cercare altre risposte SICP per una spiegazione, ma non sono riuscito a trovare qualcosa di soddisfacente. Quindi, alcuni esperti di Scheme/Lisp possono far luce su questo aspetto degli svantaggi? Grazie in anticipo per ogni idea.

+1

Grazie a tutti i rispondenti alla mia domanda, in particolare Nathan e tonio.Questo newbie in Scheme/Lisp ora gira meglio il linguaggio a causa delle tue risposte dettagliate – limist

+0

Vedi anche [Recu l'intervallo in Lisp aggiunge un punto?] (http://stackoverflow.com/q/16379657/1281433) per una spiegazione simile. –

risposta

12

'((1 2 3) 4 5 6) è in realtà un paio di liste. Ecco un altro modo di scrivere:

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

Tuttavia, la stampante evita tratteggiata coppia notazione ogni volta che si può, in modo da ottenere la prima rappresentazione, invece. La regola è:

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

Per qualsiasi x e xs. Qui, il tuo x = '(1 2 3) e xs = '(4 5 6), quindi ottieni ((1 2 3) 4 5 6).


Per vedere come contro e punteggiata-pair notazione è legato, cerchiamo di accorciare il problema per appena '(1) e '(6). Il modo più basso livello per costruire un paio di loro è questo:

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

Qui, '() è nullo, o la lista vuota.Se traduciamo questo letteralmente costellata-coppia di notazione, otteniamo questo:

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

Ma perché la stampante crolla tratteggiata-pair notazione, quando possibile, si ottiene questo, invece:

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

Grazie per la spiegazione dettagliata; Ora vedo che si tratta di una coppia di elenchi, per il crollo della notazione a coppie puntate, e dal momento che (cdr (cons x y)) fornisce la seconda lista. Ma perché (lunghezza (cons x y)) risposta 4? Non dovrebbe essere 6 (conta tutti gli elementi di entrambe le liste) o 2 (conta due liste)? – limist

+0

Ah, non importa il mio commento; Vedo che è una conseguenza della (lunghezza) funzione che danno nel libro che non si occupa di elenchi annidati. – limist

+1

@limist: Beh, una specie di. Il tuo problema (penso) sta pensando a List come un tipo di dati separato e opaco. In realtà è solo una convenzione su come utilizzare le coppie cons (vedi la risposta di tonio). Quindi, per ottenere la lunghezza 6, dovresti scrivere 'nested-list', anche se questo sarebbe veramente chiamato' tree-size' perché usa la convenzione ad albero per i conses. D'altra parte, per ottenere 2 da '(length (cons '(1 2 3)' (4 5 6))', dovresti ottenere 2 per * qualsiasi * elenco.Questo metodo ignora la convenzione lista che dice che, ad esempio, '(1) è in realtà '(cons 1'())'. La sua lunghezza è 1, non 2, a causa del modo in cui sono costruiti gli elenchi. –

10

cons utilizza il primo argomento come capo dell'elenco e il secondo come coda.

Dagli un primo elenco (1 2 3), che costituirà il capo dell'elenco risultante e un secondo elenco (4 5 6), da utilizzare come coda dell'elenco. Quindi, si termina con ((1 2 3) 4 5 6).

Gli elenchi come pettini da sinistra a destra, per finire con la lista vuota (rappresentato come o qui), e vedere come si combinano.

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

È quindi costruire:

/\ 
X Y 

Ottenere:

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

che è ((1 2 3) 4 5 6 quando rappresentato con parentesi. E questo è un paio di liste.

+0

Sì, ho cercato di semplificare un po 'il disegno, ma non è stato un successo. Cercherà di migliorare questo. – tonio

+0

Grazie per la spiegazione dello schema, ha senso ora. – limist

0

prova (lista x y) Sono sicuro che funziona su Common Lisp, non so su Scheme

1

hey, penso che potresti pensare in questo modo;

ogni volta che c'è un nullo, ci deve essere un paio di parentesi, come segue:

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

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

1. (cons xy) -> (cons (contro 1 (contro 2 (contro 3 nil))) (contro 4 (cons 5 (cons 6 nil)))) qui, il primo nil sta per una fine di una coppia che potrebbe essere espressa da parentesi; mentre il secondo nil rappresenta la fine di tutta la coppia che usa un'altra coppia di parentesi; così, ((1 2 3) 4 5 6)

2. (lista xy) -> (cons x (y cons nil); come sappiamo i x contengono una nullo, quindi deve essere (1 2 3), la seconda parte contiene due nils, modo ((1 2 3) (4 5 6));

più interno nil intende il più parentesi esterno;.

speranza può aiutare

Problemi correlati