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表达可以指两个b和a.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)
这一切都在这里的文档.