如何评估let-forms?

时间:2012-02-22 18:53:48

标签: scheme evaluation let

let - 表单允许包含多个表达式:

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

返回5

如何评估此表达式?

4 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:4)

好吧,为了以防万一,让我们明白术语。 let表单包含两部分:绑定正文

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

绑定的格式为(<variable> <expression>),正文是一系列表达式。 let的评估方式如下:

  • 创建一个本地环境,其中每个变量都绑定到相应绑定中计算表达式的结果。
  • 按顺序评估正文中的表达式。
  • 结果:正文中最后一个表达式的结果。

答案 2 :(得分:2)

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

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

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

例如,这个表达式:

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

相当于:

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

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

答案 3 :(得分:1)

首先,术语 - 变量绑定后的表达式统称为正文,而正文中的每个表达式都是正文表达式。例如:

(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中的每个正文表达式都没有副作用,则可以删除除最后一个正文表达式之外的所有表达式,而不更改程序的运行时行为。这里唯一的例外是当其中一个初步正文表达式运行缓慢/没有返回/错误时 - 消除正文表达式消除了问题,这是对程序运行时行为的改变。

然而,当使用具有副作用的函数时,能够为其副作用调用一个或多个函数然后返回值是有用的。