
1.1 编程范式
编程范式并没有统一的划分标准。本书重点分析其中两个范式:函数式编程和命令式编程。二者最重要的特征区别是状态。
在命令式语言(比如Python)中,计算的状态是通过不同命名空间中变量的值反映的。变量的值决定计算的当前状态,一条语句通过增加或改变(甚至是删除)变量来改变当前状态。“命令式”语言的每一条语句都是一个通过某种方式改变状态的命令。
本书主要关注赋值语句以及它如何改变状态。除此之外,Python中的其他语句包括用于在命令空间中改变变量规则的global、nonlocal等,用于改变变量所处语境的def、class和import等,用作判断条件确定一组语句如何改变计算状态的try、except、if、elif和else等。而循环语句,如for和while,则是将一组语句作为整体以重复改变计算状态。可见所有这些语句都是通过某种方式改变变量状态的。
理想状态下,每一条语句通过改变状态,推动计算从初始状态向期望的最终结果不断靠近。然而,这种“推动计算一步步向前”的模式难以验证。需要首先定义出最终状态,找到能达到该状态的语句,从而推导出达到该状态需要的前提条件,然后重复上述步骤,直到找到一个可接受的初始状态。
在函数式语言中,使用“对函数求值”这一更简单的概念代替改变变量值的“状态”,每次对函数求值都会在现有对象的基础上创建一个或多个新对象。函数式程序即函数的组合,相应的开发过程是:首先设计一组易于理解的底层函数,然后在此基础上设计符合业务需求的高级函数。相比于由复杂的流程控制组成的指令集合,高级函数更容易可视化。
形式上,函数求值更接近算法的数学表达。以简单的代数形式设计算法,便于处理特殊情况和边界条件,而且函数更有可能按照预期工作,也便于编写单元测试用例。
请注意,通常函数式程序比功能相同的命令式(面向对象或者过程式的)程序更加简洁明了和高效,但这些优点并不是自然而然的,需要仔细地设计,但付出的努力通常少于设计功能类似的过程式程序。