2.3 Scheme表达式求值

我们已经知道了常量对象的求值规则,比如数字和字符串。常量的值就是它自己。你可能自己脑补了函数调用的求值规则。(procedure arg1 ... argn),这儿,procedure是一个表达式,用来表示一个 Scheme 过程(函数),arg1 ... argn 同样是表达式,用来表示参数。一个可能的求值规则是:

  • 找到 procedure 的值
  • 找到 arg1的值
  • ......
  • 找到 argn的值
  • procedure 的值应用到 arg1 ... argn 的值上面

思考简单的函数调用(+ 3 4)+的值是一个加法函数,3 的值就是 3,4 的值就是 4, 将 3 和 4 作为参数传递给函数 + 得到返回值 7, 所以 (+ 3 4)的个表达式的值就是 7 这个对象。

重复这个过程,我们就可以得到嵌套的表达式 (* (+ 3 4) 2) 的值。*的值是一个乘法函数,(+ 3 4)的值上面已经得到了 7, 2 的值是2. 将乘法函数应用于 7 和 2,我们得到最终的值是 14.

这个求值规则对函数调用有效,对quote表达式无效,因为quote不对它的子表达式求值。对quote表达式的求值类似于对常量的求值。

常量对象(字面量),过程(函数)以及引用(quote)是 Scheme 提供的众多语法形式中的三种。幸运的是,只有很少一部分其它语法形式需要 Scheme 直接理解,这些被称为“核心”语法形式,剩下的那些是“扩展”的语法定义。在本章的剩下的内容里,我们将要介绍剩下的那部分核心语法,以及少量的扩展语法。3.1节概括了核心语法并且介绍了语法扩展的机制。

在我们学习更多的语法及函数之前,关于函数调用的求值有两点值得注意。首先,上面给出的求值顺序是特定的,函数调用的子表达式从左到右依次求值,也就是 procedurearg1 之前求值,而 arg1arg2 之前求值。其实这不是强制的。一个 Scheme 求值器可以自由决定求值的顺序,从左到右或者从右到左,或者以别的任何顺序进行求值。甚至在同一个 Scheme 实现里,也会对不同的过程使用不同的求值顺序。

第二点要注意的是,procedure 采用与 arg1 ... argn 相同的方式求值。procedure 是一个变量名,用来命名一个过程。然而处在 procedure位置上的不一定必须是一个变量,也可以是另外一个表达式。在练习 2.2.3 里,要求你判断这个表达式的值((car (list + - * /)) 2 3),在这里,作为函数被调用的并不是某个被命名的函数,而是这个表达式(car (list + - * /)),它的值就是加法函数+

练习 2.3.1

写出下面的表达式的求值步骤

((car (cdr (list + - * /))) 17 5)

results matching ""

    No results matching ""