Confundido por la diferencia entre let y let * in Scheme

¿Alguien puede explicar la diferencia simplemente? No creo entender el concepto de los libros de texto / sitios que he consultado.

Si usa let , no puede hacer referencia a enlaces definidos previamente en la misma expresión let . Por ejemplo, esto no funcionará:

 (let ((x 10) (y (+ x 6))) ; error! unbound identifier in module in: x y) 

Pero si usa let* , es posible hacer referencia a enlaces anteriores en la misma expresión let* :

 (let* ((x 10) (y (+ x 6))) ; works fine y) => 16 

Todo está aquí en la documentación.

Let es paralelo, (tipo de, ver debajo) let* es secuencial. Let traducir como

 ((lambda(abc) ... body ...) a-value b-value c-value) 

pero let* como

 ((lambda(a) ((lambda(b) ((lambda(c) ... body ...) c-value)) b-value)) a-value) 

y, por lo tanto, está creando bloques de ámbito nesteds donde la expresión de b-value puede hacer referencia a a , y la expresión de c-value puede referirse tanto a b a . a-value pertenece al scope externo. Esto también es equivalente a

 (let ((a a-value)) (let ((b b-value)) (let ((c c-value)) ... body ... ))) 

También hay letrec , que permite enlaces recursivos, donde todas las variables y expresiones pertenecen a un scope compartido y pueden referirse entre sí (con algunas advertencias relativas a la inicialización). Es equivalente a

 (let ((a *undefined*) (b *undefined*) (c *undefined*)) (set! a a-value) (set! b b-value) (set! c c-value) ... body ... ) 

( en Racket , también disponible como letrec* en Scheme, desde R6RS ), o para

 (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 ... )) 

( en Scheme ).

actualización: let no evalúa en realidad sus expresiones de valor en paralelo, es solo que todas se evalúan en el mismo entorno inicial donde aparece el formulario let . Esto también es claro a partir de la traducción basada en lambda : primero las expresiones de valor se evalúan cada una en el mismo entorno externo , y los valores resultantes se recostackn, y solo entonces se crean nuevas ubicaciones para cada id y los valores se ponen cada uno en su ubicación. Todavía podemos ver la secuencia si una de las expresiones de valor muta un almacenamiento (es decir, datos, como una lista o una estructura) a los que se accede por uno posterior.

Intereting Posts