2014-04-11 10 views
7

Questo passo On Lisp è veramente confusa - non è chiaro come la restituzione di un elenco citato come '(oh my) può effettivamente alterare come la funzione si comporta in futuro: non sarà la lista restituita essere generato di nuovo nella funzione da zero, la prossima volta che viene chiamato?Bizzarro lista esempio citato da On Lisp

Se definiamo esclamare in modo che il suo valore di ritorno incorpora un elenco citato,

(defun exclaim (expression) 
    (append expression ’(oh my))) 

Poi alcuna modifica distruttiva successiva del valore di ritorno

(exclaim ’(lions and tigers and bears)) 
-> (LIONS AND TIGERS AND BEARS OH MY) 
(nconc * ’(goodness)) 
-> (LIONS AND TIGERS AND BEARS OH MY GOODNESS) 

potrebbe modificare l'elenco all'interno della funzione:

(exclaim ’(fixnums and bignums and floats)) 
-> (FIXNUMS AND BIGNUMS AND FLOATS OH MY GOODNESS) 

Per rendere la prova esclamare contro tali problemi, dovrebbe essere scritto:

(defun exclaim (expression) 
    (append expression (list ’oh ’my))) 

Come esattamente è che l'ultima chiamata al exclaim aggiungendo la parola goodness al risultato? La funzione non fa riferimento a nessuna variabile esterna, quindi in che modo la chiamata separata a nconc ha effettivamente modificato il funzionamento della funzione exclaim?

+0

Vedo che hai una risposta, ma dai un'occhiata a [questa risposta] (http://stackoverflow.com/a/18790523/1281433) per ulteriori discussioni e risorse –

+1

Inoltre, questo è probabilmente un duplicato di [Scenario Strange Lisp Quoting - Graham's On Lisp, pagina 37] (http://stackoverflow.com/q/4003115/1281433). –

risposta

8

a) gli effetti della modifica degli elenchi letterali non sono definiti nello standard Common Lisp. Quello che vedi qui come esempio è un possibile comportamento.

(1 2 3 4) è un elenco letterale. Ma una chiamata a LIST come in (list 1 2 3 4) restituisce un elenco appena acquistato in fase di esecuzione.

b) l'elenco è letterale nel codice della funzione. Ogni chiamata restituirà esattamente questo oggetto dati. Se si desidera fornire un nuovo elenco per ogni chiamata, è necessario utilizzare qualcosa come ELENCO o ELENCO DI COPIE.

c) Poiché l'elenco restituito è sempre lo stesso oggetto di dati letterali, modificandolo può avere questo effetto come descritto. Si potrebbe anche immaginare che si verifichi un errore se il codice e i suoi oggetti sono allocati in una memoria di sola lettura. La modifica dell'elenco proverebbe quindi a scrivere nella memoria di sola lettura.

d) Una cosa da tenere a mente quando si lavora con i dati della lista letterale nel codice sorgente è questa: il compilatore Lisp è libero di ottimizzare la memoria. Se una lista dovesse trovarsi più volte nel codice sorgente, un compilatore può rilevarlo e creare solo UN elenco. Tutti i vari posti quindi punterebbero a questa lista. Pertanto, la modifica dell'elenco avrebbe l'effetto di rendere visibili questi cambiamenti in diversi punti.

Ciò può verificarsi anche con altri oggetti di dati letterali come array/vettori.

Se la struttura dati fa parte del codice, si restituisce questa struttura dati interna, si modifica questa struttura dati, quindi si tenta di modificare il codice.

Nota anche che il Lisp può essere eseguito da un interprete. L'interprete lavora tipicamente sulla struttura sorgente Lisp - il codice non è codice macchina, ma interpreta il codice Lisp come dati Lisp. Qui potresti essere in grado di modificare il codice sorgente in fase di runtime, non solo i dati incorporati nel codice sorgente.

+0

quindi stai dicendo che il ''(oh mio)' sopravvive dopo che la funzione ritorna, vive come un pezzo reale di dati persistenti, e che 'nconc' sta mutando i dati e rendendoli'' (oh mio Dio) 'cosicché quando viene eseguito nuovamente 'exclaim', sta usando un nuovo valore in quei dati? – johnbakers

+0

Sì. 'exclaim' stesso non muta nulla, fatto da' nconc'. 'exclaim' rende semplicemente visibili i nuovi contenuti della lista quotata modificata. – gsg

+0

@Rainer: è (a) vero per tutte le liste o solo elenchi letterali? – Baggers

Problemi correlati