谁能简单解释一下区别?我不认为我从我咨询过的教科书/网站中理解了这个概念。
问问题
10929 次
2 回答
30
Let
是并行的,(有点;见下文) let*
是顺序的。Let
翻译为
((lambda(a b c) ... body ...)
a-value
b-value
c-value)
但let*
作为
((lambda(a)
((lambda(b)
((lambda(c) ... body ...)
c-value))
b-value))
a-value)
并因此创建嵌套范围块,其中b-value
表达式可以引用a
,c-value
表达式可以同时引用b
和a
。a-value
属于外部范围。这也相当于
(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 ... )
(在 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 ... ))
(在方案中)。
update:let
实际上并没有并行地评估它的值表达式,只是它们都在let
表单出现的相同初始环境中被评估。这从基于 - 的翻译中也很清楚:首先在相同的外部环境lambda
中评估每个值表达式,并收集结果值,然后才为每个id创建新位置,并将值放入每个位置. 如果其中一个值表达式改变了由后续存储访问的存储(即数据,如列表或结构),我们仍然可以看到顺序性。
于 2013-02-21T15:28:56.837 回答
29
如果使用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
这一切都在文档中。
于 2013-02-21T13:33:56.750 回答