【问题标题】:How are let-forms evaluated?如何评估 let-forms?
【发布时间】:2012-03-13 03:43:21
【问题描述】:

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

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

返回5

如何评估这个表达式?

【问题讨论】:

    标签: scheme evaluation let


    【解决方案1】:

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

    (let ((x 4)) (begin x (+ x 1)))
    
    【解决方案2】:

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

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

    绑定的形式为(&lt;variable&gt; &lt;expression&gt;),主体是一系列表达式。 let 的评估方式如下:

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

    【讨论】:

      【解决方案3】:

      您所描述的情况出现在 Scheme 的多个部分中,而不仅仅是在 let 表达式中。接下来...

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

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

      例如,这个表达式:

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

      相当于:

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

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

      【讨论】:

        【解决方案4】:

        首先,术语——变量绑定之后的表达式统称为body,body中的每一个表达式都是一个body表达式。例如:

        (let ((variable-1 value-1)
              (variable-2 value-2))
          body-expression-1
          body-expression-2)
        

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-03-15
          • 2010-10-13
          • 2012-01-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多