在C/Java学习中,会了解和求值相关的很多知识。例如:
- 表达式的求值顺序,
- b-e ? exp1: exp2求值顺序
- 函数调用时,实参如何传递给方法的形参
这些知识背后,是设计编程语言时采用的求值策略(Evaluation Strategy)。求值策略决定函数的实参应该在何时被求值,以及实参以什么方式传递到函数体内。
虽然看起来求值策略仅仅涉及到函数调用,其实表达式的操作符,条件表达式的?都是一个函数调用。函数的实参求值时机分两种:
applicative-order Vs.normal-order
饥饿求值(Strict/Eager Evaluation)和延迟计算/惰性求值 (delay computing /Lazy Evaluation)。
1. 应用序求值
先看表达式的计算过程:
(* (+ 1 (- 2 1)) (- 2 1))
= (* (+ 1 1) (- 2 1))
= (* 2 (- 2 1))
= (* 2 1)
= 2
如果将该表达式采用树形表示,其求值顺序按“最左最内/leftmost innermost”方式求值,也称应用序 (Applicative order,实用序)求值或饥饿求值(序同后序、前序的序)。先求最左的*,这是操作符*,后面是其参数;然后对各个参数求值。递归地,找到最内部的表达式先求得结果。
对于函数调用,通常也是应用序求值。简单地说,函数调用时先计算所有实参的值。
(define (square x) (* x x))
(square (+ 1 2))
=(square 3)
= (* 3 3)