Confundido por la diferencia entre let y let* en el Esquema


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

 24
Author: user2095626, 2013-02-21

2 answers

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 usas let*, es posible referirse a enlaces anteriores en la misma expresión let*:

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

Está todo aquí en la documentación.

 24
Author: Óscar López,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-21 13:33:56

Let es en paralelo, (tipo de; ver más abajo)let* es secuencial. Let se traduce como

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

Pero let* as

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

Y está creando así bloques de ámbito anidados donde la expresión b-value puede referirse a a, y la expresión c-value puede referirse tanto a b como a a. a-value pertenece al ámbito externo. Esto también equivale a

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

También Hay letrec, permitiendo recursiva enlaces, donde todas las variables y expresiones pertenecen a un ámbito 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 raqueta, también disponible como letrec* en Scheme, desde R6RS), o hasta

(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 en realidad no evalúa 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 se desprende claramente de la traducción basada en lambda: primero se evalúan las expresiones de valor cada una en el mismo entorno externo, y se recopilan los valores resultantes, y solo entonces se crean nuevas ubicaciones para cada id y los valores se colocan cada uno en su ubicación. Todavía podemos ver la secuencialidad si una de las expresiones de valor muta un almacenamiento (es decir, datos, como una lista o una estructura) al que una.

 27
Author: Will Ness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-06 10:19:30