let
-forms 允许在内部包含多个表达式:
(let ((x 4))
x
(+ x 1))
返回5
。
这个表达式是如何计算的?
这称为隐式begin
,换句话说,您的代码被评估为就好像它是编写的一样:
(let ((x 4)) (begin x (+ x 1)))
好吧,让我们弄清楚术语以防万一。let
表单有两个部分:绑定和主体:
(let (<zero or more bindings>)
<one or more body expressions>)
绑定的形式(<variable> <expression>)
为 ,主体是表达式序列。Alet
的评估如下:
您所描述的情况发生在 Scheme 的多个部分中,而不仅仅是在let
表达式中。在下面的 ...
let
表达式中的变量绑定列表之后lambda
表达式中的参数列表之后(因此,在过程定义中的参数列表之后)cond
表达式中的每个子句之后...您可以编写表达式列表。这些表达式隐含地包含在一个begin
特殊的形式中,计算的顺序是从左到右,所有的表达式依次计算,但返回的值是最后一个表达式的值。
例如,这个表达式:
(cond ((= 1 1) 1 2 3))
相当于:
(cond ((= 1 1) (begin 1 2 3)))
在这两种情况下,返回值都是3
,因为这是列表中最后一个表达式的值。
一、术语——变量绑定之后的表达式统称为body,body中的每一个表达式都是一个body表达式。前任:
(let ((variable-1 value-1)
(variable-2 value-2))
body-expression-1
body-expression-2)
正文表达式包含在begin
-(let ((x 2)) x (+ x 1))
中,与 . 相同(let ((x 2)) (begin x (+ x 1)))
。
中的每个主体表达式都begin
被求值,最终表达式的返回值被用作整个主体的返回值。例如:(begin (+ x 1) (+ x 2))
将评估(+ x 1)
然后(+ x 2)
返回评估的结果(+ x 2)
。
如果其中的每个主体表达式begin
都没有副作用,则可以删除除最后一个主体表达式之外的所有主体表达式,而不会改变程序的运行时行为。这里唯一的例外是当一个初步的主体表达式运行缓慢/不返回/出错时——消除主体表达式消除了问题,这是对程序运行时行为的改变。
但是,当使用具有副作用的函数时,调用一个或多个函数以获取其副作用然后返回值的能力很有用。