2012-06-13 4 views
5

Sono po 'confuso dal risultato di questo esempio:set-car! e lasciate in un linguaggio schema

(define mk-q 
    (lambda() 
    (let ([l '(x)]) 
     (cons l l)))) 


(define q (mk-q)) 

q 
=> ((x) x) 

(set-car! (cdr q) 'y) 
=> ((y) y) 

Mi chiedo il motivo per cui entrambe le x gli atomi sono stati sostituiti da set-car! procedura (la mia prima ipotesi per quello che sarebbe stato il risultato è stato ((x) y))?

Ad esempio:

(define mk-q2 
    (lambda() 
    (let ([l '(x)]) 
     (cons l (cons l l))))) 

(define q2 (mk-q2)) 
(set-car! (cdr q2) 'y) 
=> ((x) y x) which fits my understanding of set-car! 

Perché sono entrambi x s nel primo esempio sostituito?

+2

Perché una cella cons è essenzialmente due puntatori a valori. Quando scrivi '(cons l l)' crei due puntatori allo stesso oggetto. Quando si modifica l'oggetto, entrambe le voci puntano ancora allo stesso oggetto. –

+0

Inizialmente l'ho interpretato erroneamente come set-carl, il che era divertente in un certo senso della forza della fame in acqua adolescenti. – Bill

risposta

4

Nel primo esempio, è necessario qualcosa di equivalente a questo:

(define cell (cons 'x null)) 
(define q (cons cell cell)) 

Come si può vedere, c'è solo unocons cella con x nella posizione car, che è condivisa in due parti differenti della struttura dell'elenco risultante. Quando esegui (set-car! (cdr q) 'y) lo x nella cella singola viene sostituito da in tutte le parti in cui viene condiviso. Ricordando che entrambi (cons 'x null) cellule sono in realtà la stessa, stiamo andando da questo:

(cons (cons 'x null) (cons 'x null)) 
; '((x) x) 

a questo:

(cons (cons 'y null) (cons 'y null)) 
; '((y) y) 

Per il secondo esempio valgono le stesse considerazioni (tutti e tre i (cons 'x null) le cellule sono in realtà la stesso condivisa), ma si sta sostituendo una cellula intera cons, in modo sostanzialmente stiamo andando da questo:

(cons (cons 'x null) (cons (cons 'x null) (cons 'x null))) 
; '((x) (x) x) 

a questo:

(cons (cons 'x null) (cons 'y (cons 'x null))) 
; '((x) y x) 

per dimostrare il mio punto che entrambi gli esempi in questione dimostrano la stessa situazione, eseguire questo espressioni:

(define q2 (mk-q2)) 
(set-car! (cadr q2) 'y) ; notice the extra `a` 
q2 
=> '((y) (y) y) 
Problemi correlati