3

let-forms 允许在内部包含多个表达式:

(let ((x 4))
   x
  (+ x 1))

返回5

这个表达式是如何计算的?

4

4 回答 4

8

这称为隐式begin,换句话说,您的代码被评估为就好像它是编写的一样:

(let ((x 4)) (begin x (+ x 1)))
于 2012-02-22T18:59:44.950 回答
4

好吧,让我们弄清楚术语以防万一。let表单有两个部分:绑定主体

(let (<zero or more bindings>)
  <one or more body expressions>)

绑定的形式(<variable> <expression>)为 ,主体是表达式序列。Alet的评估如下:

  • 创建一个本地环境,其中每个变量都绑定到对相应绑定中的表达式求值的结果。
  • 按顺序评估正文中的表达式。
  • 结果:正文中最后一个表达式的结果。
于 2012-02-22T19:13:34.017 回答
2

您所描述的情况发生在 Scheme 的多个部分中,而不仅仅是在let表达式中。在下面的 ...

  • let表达式中的变量绑定列表之后
  • lambda表达式中的参数列表之后(因此,在过程定义中的参数列表之后)
  • cond表达式中的每个子句之后

...您可以编写表达式列表。这些表达式隐含地包含在一个begin特殊的形式中,计算的顺序是从左到右,所有的表达式依次计算,但返回的值是最后一个表达式的值。

例如,这个表达式:

(cond ((= 1 1) 1 2 3))

相当于:

(cond ((= 1 1) (begin 1 2 3)))

在这两种情况下,返回值都是3,因为这是列表中最后一个表达式的值。

于 2012-02-22T19:10:20.570 回答
1

一、术语——变量绑定之后的表达式统称为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都没有副作用,则可以删除除最后一个主体表达式之外的所有主体表达式,而不会改变程序的运行时行为。这里唯一的例外是当一个初步的主体表达式运行缓慢/不返回/出错时——消除主体表达式消除了问题,这是对程序运行时行为的改变。

但是,当使用具有副作用的函数时,调用一个或多个函数以获取其副作用然后返回值的能力很有用。

于 2012-02-23T04:56:38.580 回答