表达式与求值
介绍函数式编程思想、Racket 表达式的前缀表示法与嵌套,以及应用序求值规则。
导言
在本小节中,你将进一步学习函数式编程,还将学习表达式和求值。
函数式编程
在深入 Racket 语言本身之前,我们先来看看本课这个看似简单的”大思想”。简言之:求值一个表达式(expression)时,可以把一个函数返回的值用作另一个函数的实参(argument)。通过这样把两个函数”连接”起来,我们就发明了一个新的、第三个函数。举个例子,假设我们有一个函数,作用是在词的末尾加上字母 s(以伪代码表示):
add-s("run") = "runs"
还有一个函数,把两个词组合成一个句子:
sentence("day", "tripper") = "day tripper"
我们可以把这两个函数组合起来,创造一个新函数,用来表示动词的第三人称单数形式:
third-person(verb) = sentence("she", add-s(verb))
把这个通用公式用在某个具体的动词上,就是这样的:
third-person("sing") = "she sings"
用 Racket 来写则是这样:
(define (third-person verb)
(sentence 'she (add-s verb)))
如果你觉得这一点令人困惑或违反直觉,别担心;关于这个概念,你会有大量的练习。尽管如此,我们将会看到,通过这种方式把函数连接起来,可以表达种类繁多的计算算法。这种”连接”就是我们所说的函数式编程。
表达式
大思想: 你可以向 Racket 提”问题”,这些问题称为表达式(expression)。Racket 解释器随后会”思考”你的问题,也就是求值(evaluate)你的表达式。然后你会得到答案,称为值(value)。我们输入 Racket 的所有内容(只要不报错)都是表达式。
当你希望 Racket 做 某件事时(例如把两个数相加),你要用前缀表示法(prefix notation)写一个表达式。尽管所有不报错的输入都是表达式,但最有意思的那类是过程调用(call to a procedure)。看看下面的例子:
(+ 3 4)
在这个例子中:
+是过程(procedure),即表达式的运算符(operator)3是+的实参,即表达式的操作数(operand)4同样是一个实参/操作数
这种语法允许我们嵌套(nest)表达式:
(* (max 2 3) (/ 8 4))
*、max和/都是过程*是大表达式的运算符,而(max 2 3)和(/ 8 4)是大表达式的操作数max是第一个子表达式的运算符,而2和3是第一个子表达式的操作数/是第二个子表达式的运算符,而8和4是第二个子表达式的操作数
检验理解
以下哪些是合法的 Racket 表达式?选择所有适用的项。
现在,打开你电脑上的 Racket 解释器,亲自尝试一些表达式吧。
求值
Racket 使用应用序(Applicative Order)(第 1 课会讲授)来求值表达式,规则如下:
- 求值运算符和操作数
- 将运算符应用于操作数
Racket 实际理解和求值表达式的方式相当复杂,我们会在第 11 课讲解。现在,继续进入下一小节吧!