由于let和let*之间的差异而感到困惑

use*_*626 25 scheme let

有人能简单解释一下这个区别吗 我不认为我理解我所咨询的教科书/网站的概念.

Wil*_*ess 28

Let是平行的,(种类;见下文) let*是顺序的.Let翻译为

((lambda(a b c)  ... body ...)
  a-value
  b-value
  c-value)
Run Code Online (Sandbox Code Playgroud)

let*作为

((lambda(a)
    ((lambda(b)
       ((lambda(c) ... body ...)
        c-value))
     b-value))
  a-value)
Run Code Online (Sandbox Code Playgroud)

并因此创建嵌套范围块,其中b-value表达可以指a,和c-value表达可以指两个ba.a-value属于外部范围.这也相当于

(let ((a a-value))
  (let ((b b-value))
    (let ((c c-value))
      ... body ... )))
Run Code Online (Sandbox Code Playgroud)

还有letrec,允许递归绑定,其中所有变量和表达式都属于一个共享范围,并且可以相互引用(有一些与初始化有关的警告).它等同于

(let ((a *undefined*) (b *undefined*) (c *undefined*))
  (set! a a-value)
  (set! b b-value)
  (set! c c-value)
  ... body ... )
Run Code Online (Sandbox Code Playgroud)

(在Racket中,也可以letrec*在Scheme中获得,因为R6RS),或者

(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 ... ))
Run Code Online (Sandbox Code Playgroud)

(在计划中).

更新:let并不实际并行地评估其值表达式,只是它们都在let表单出现的相同初始环境中进行评估.这也是从清lambda为基础的翻译:首先将该值表达式求值在同一个,外环境中的每个,并将得到的值被收集,并且只有然后新的位置创建的每个ID和值确定它们各自的位置.如果一个值表达式改变了后续访问的存储(即数据,如列表或结构),我们仍然可以看到顺序性.


Ósc*_*pez 26

如果使用let,则无法引用先前在同一let表达式中定义的绑定.例如,这不起作用:

(let ((x 10)
      (y (+ x 6))) ; error! unbound identifier: x
  y)
Run Code Online (Sandbox Code Playgroud)

但是如果你使用let*,可以在同一个let*表达式中引用先前的绑定:

(let* ((x 10)
       (y (+ x 6))) ; works fine
  y)
=> 16
Run Code Online (Sandbox Code Playgroud)

这一切都在这里的文档.