# 4.2.1正常订单和适用订单

> 译者： [https://sicp.comp.nus.edu.sg/chapters/82](https://sicp.comp.nus.edu.sg/chapters/82)

在我们开始讨论评估模型的 [1.1](2) 部分中，我们注意到JavaScript是一种_应用顺序_语言，即， 应用函数时，将评估JavaScript函数。 相反，_正序_语言会延迟对函数自变量的求值，直到需要实际的自变量值为止。 将函数自变量的求值延迟到最后一个可能的时刻（例如，直到原始操作需要它们）才称为_惰性求值_。 [[1]](82#footnote-1) 考虑功能

```js
function try_me(a, b) {
    return a === 0 ? 1 : b;	
}
```

评估`try_me(0, head(null));`会在JavaScript中产生错误。 使用惰性评估，不会有任何错误。 评估表达式将返回1，因为永远不会评估参数`head(null)`。

利用懒惰求值的示例是函数`unless`的定义

```js
function unless(condition, usual_value, exceptional_value) {      
    return condition ? exceptional_value : usual_value;
}
```

that can be used in expressions such as

```js
unless(xs === null,
       head(xs),	
       display("error: xs should not be null"));
```

这不适用于应用顺序语言，因为通常值和例外值都将在调用`unless`之前进行评估（比较练习 [1.6](9#ex_1.6) ）。 惰性求值的优点是，即使某些函数（例如`unless`）的求值会产生错误或不会终止，它们也可以执行有用的计算。

如果在评估参数之前输入函数的主体，我们就说该函数在该参数中是_非严格_。 如果在输入函数主体之前对参数进行了求值，则可以说该函数在该参数中是_严格_。 [[2]](82#footnote-2)

在纯粹的应用顺序语言中，所有功能在每个参数中都是严格的。 在纯正序语言中，所有复合函数在每个参数中都是非严格的，而原始函数可以是严格的也可以是非严格的。 还有一些语言（请参阅练习 [4.22](83#ex_4.22) ）使程序员能够对其所定义功能的严格性进行详细控制。

可以有效地使函数成为非严格函数的一个引人注目的示例是`pair`（或通常，几乎任何数据结构的构造函数）。 即使元素的值未知，也可以进行有用的计算，组合元素以形成数据结构并对结果数据结构进行操作。 例如，在不知道列表中各个元素的值的情况下计算列表的长度是很有意义的。 我们将在 [4.2.3](84) 部分中利用此思想，将第3章的流实现为由非严格`pair`对组成的列表。

<exercise>Suppose that (in ordinary applicative-order JavaScript) we define `unless` as shown above and then define `factorial` in terms of `unless` as

```js
function factorial(n) {
    return unless(n === 1,
                  n * factorial(n - 1),
                  1);
}
```

What happens if we attempt to evaluate `factorial(5)`? Will our definitions work in a normal-order language?<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_82_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise><exercise>Ben Bitdiddle and Alyssa P. Hacker disagree over the importance of lazy evaluation for implementing things such as `unless`. Ben points out that it's possible to implement `unless` in applicative order as a new kind of expression, akin to conditional expressions. Alyssa counters that, if one did that, `unless` would be merely syntax, not a function that could be used in conjunction with higher-order functions. Fill in the details on both sides of the argument. Show how to define the evaluation of `unless` as a new kind of expression (as we defined the evaluation of conditional expressions in section <ref name="sec:conditionals">[1.1.6](8)</ref>), and give an example of a situation where it might be useful to have `unless` available as a function, rather than as a new expression syntax.<button class="btn btn-secondary solution_btn" data-toggle="collapse" href="#no_solution_82_1_div">Add solution</button>There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in [Github](https://github.com/source-academy/sicp).</exercise>

* * *

[[1]](82#footnote-link-1) The difference between the <quote>lazy</quote> terminology and the <quote>normal-order</quote> terminology is somewhat fuzzy. Generally, <quote>lazy</quote> refers to the mechanisms of particular evaluators, while <quote>normal-order</quote> refers to the semantics of languages, independent of any particular evaluation strategy. But this is not a hard-and-fast distinction, and the two terminologies are often used interchangeably.

[[2]](82#footnote-link-2) The <quote>strict</quote> versus <quote>non-strict</quote> terminology means essentially the same thing as <quote>applicative-order</quote> versus <quote>normal-order,</quote> except that it refers to individual functions and arguments rather than to the language as a whole. At a conference on programming languages you might hear someone say, <quote>The normal-order language Hassle has certain strict primitives. Other functions take their arguments by lazy evaluation.</quote>

