Qualcuno può spiegare la differenza semplicemente? Non penso di aver capito il concetto dai libri di testo/siti che ho consultato.Confuso dalla differenza tra let e let * in Schema
risposta
Se si utilizza let
, non è possibile fare riferimento ai collegamenti precedentemente definiti nella stessa espressione let
. Ad esempio, questo non funzionerà:
(let ((x 10)
(y (+ x 6))) ; error! unbound identifier in module in: x
y)
Ma se si utilizza let*
, è possibile fare riferimento a attacchi precedenti nella stessa let*
espressione:
(let* ((x 10)
(y (+ x 6))) ; works fine
y)
=> 16
E 'tutto here nella documentazione.
Non lo vedo chiaramente nella documentazione (dove il tuo link punta, versione corrente 5.3.6), quindi ero anche confuso. La documentazione di 'let' dice che" La prima forma valuta il 'val-exprs' da sinistra a destra, ...", quindi non è chiaro che siano valutati in parallelo. – Alexey
@Alexey non li valuta in parallelo. Come dice la documentazione, * "La prima forma valuta il' val-exprs' da sinistra a destra, crea una nuova posizione per ciascun 'id', e colloca i valori nelle posizioni" * - che significa, prima vengono valutati e i valori risultanti vengono raccolti, e solo *** poi *** vengono create nuove posizioni per ogni * 'id' * e i valori vengono inseriti ciascuno nella sua posizione. È ancora possibile vedere la sequenzialità se uno dei * 'val-exprs' * muta una memoria (cioè dati, come lista o struct) a cui si accede da una successiva. –
Let
è parallela, (tipo; vedi sotto)let*
è sequenziale. Let
traduce come
((lambda(a b c) ... body ...)
a-value
b-value
c-value)
ma let*
come
((lambda(a)
((lambda(b)
((lambda(c) ... body ...)
c-value))
b-value))
a-value)
e sta creando così isolati scope nidificati dove b-value
espressione può riferirsi a a
e c-value
espressione può riferirsi sia b
e a
. a-value
appartiene all'ambito esterno. Questo è anche equivalente a
(let ((a a-value))
(let ((b b-value))
(let ((c c-value))
... body ...)))
C'è anche letrec
, permettendo attacchi ricorsive, in cui tutte le variabili e le espressioni appartenenti ad un ambito condiviso e possono fare riferimento gli uni agli altri (con alcuni avvertimenti relativi alla inizializzazione). È equivalente sia per
(let ((a *undefined*) (b *undefined*) (c *undefined*))
(set! a a-value)
(set! b b-value)
(set! c c-value)
... body ...)
(in Racket, disponibile anche come letrec*
nello Schema, dal R6RS), o per
(let ((a *undefined*) (b *undefined*) (c *undefined*))
(let ((_x_ a-value) (_y_ b-value) (_z_ c-value)) ; unique identifiers
(set! a _x_)
(set! b _y_)
(set! c _z_)
... body ...))
(in Scheme).
aggiornamento: let
non valuta effettivamente le sue espressioni di valore in parallelo, è solo che sono tutte valutate nello stesso ambiente iniziale in cui viene visualizzato il modulo let
. Questo è anche evidente dal lambda
Traduzione sede: primi le espressioni valori vengono valutate ciascuna nello stesso ambiente, esterno, ed i valori risultanti vengono raccolti, e solo allora nuove posizioni vengono creati per ogni id e i valori sono messi ciascuno nella sua posizione. Possiamo ancora vedere la sequenzialità se una delle espressioni di valore muta una memoria (cioè dati, come una lista o una struttura) cui si accede da una successiva.
possibile duplicato di [Schema Confusing of Let and Let \ *] (http: // stackoverflow.it/questions/8036840/scheme-confusing-of-let-and-let) –
@DavidPfeffer - Non sembra essere un problema. Quello che si chiede è un'interazione molto specifica di 'let' s e 'let *' s, mentre questa richiede una panoramica generale. – Inaimathi
semplicemente confuso spiegazione umana dell'esecuzione della macchina: o – Nishant