Scheme 被let和let*in方案之间的差异弄糊涂了

Scheme 被let和let*in方案之间的差异弄糊涂了,scheme,let,Scheme,Let,有人能简单地解释一下这种区别吗?我不认为我从我参考过的教科书/网站中理解了这个概念。如果使用let,就不能引用同一let表达式中出现的其他绑定 例如,这将不起作用: (let ((x 10) (y (+ x 6))) ; error! unbound identifier: x y) 但是如果使用let*,则可以引用出现在同一let*表达式中的以前的绑定: (let* ((x 10) (y (+ x 6))) ; works fine y) => 16

有人能简单地解释一下这种区别吗?我不认为我从我参考过的教科书/网站中理解了这个概念。

如果使用
let
,就不能引用同一
let
表达式中出现的其他绑定

例如,这将不起作用:

(let ((x 10)
      (y (+ x 6))) ; error! unbound identifier: x
  y)
但是如果使用
let*
,则可以引用出现在同一
let*
表达式中的以前的绑定:

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

这些都在文档中。

是并行的,(有点像;见下文)
让*
是顺序的
翻译为

((lambda(a b c)  ... body ...)
  a-value
  b-value
  c-value)
但是
让*
作为

((lambda(a)
    ((lambda(b)
       ((lambda(c) ... body ...)
        c-value))
     b-value))
  a-value)
并因此创建嵌套的作用域块,
b-value
表达式可以引用
a
c-value
表达式可以引用
b
a
<代码>a值属于外部范围。这也相当于

(let ((a a-value))
  (let ((b b-value))
    (let ((c c-value))
      ... body ... )))
还有一个
letrec
,允许递归绑定,其中所有变量和表达式都属于一个共享范围,并且可以相互引用(与初始化相关的一些注意事项)。这相当于

(let ((a *undefined*) (b *undefined*) (c *undefined*))
  (set! a a-value)
  (set! b b-value)
  (set! c c-value)
  ... body ... )
(,也可作为方案中的letrec*提供,自),或

()


更新:
let
实际上并没有并行计算其值表达式,只是它们都是在出现
let
表单的相同初始环境中计算的。从基于
lambda
的转换中也可以清楚地看到这一点:首先在相同的外部环境中对每个值表达式进行求值,并收集结果值,然后只为每个id创建,然后为每个id创建新位置,并将每个值放在其位置。如果其中一个值表达式改变了由后续表达式访问的存储(即数据,如列表或结构),我们仍然可以看到顺序性。

可能重复的@DavidPfeffer-似乎不是重复的。这个人问的是嵌套的
let
s和
let*
s的一个非常具体的交互,而这个人问的是一个总体概述。只是混淆了机器执行的人类解释:oI在文档中看不清楚(您的链接点在哪里,当前的版本5.3.6),所以我也很困惑。
let
的文档说明“第一个表单从左到右计算
val exprs
,”,因此不清楚它们是否是并行计算的。@Alexey它不会并行计算它们。正如文档中所说,“第一个表单从左到右计算
val exprs
,为每个
id
创建一个新位置,并将值放入位置”——这意味着首先计算值并收集结果值,只有这样,才会为每个
id
创建新的位置,并将每个值放入其位置。如果
val exprs
中的一个对后续存储访问的存储(即数据,如列表或结构)进行了变异,则仍然可以看到顺序性。
(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 ... ))