第 12 章:缺失结果、异常与可变状态
除法可能遇到零除数,查找可能没有结果。如果用零或空字符串代替失败,调用者就难以分辨它是正常结果还是失败标记。本章先用可选值明确表示“有结果”和“没有结果”,再介绍异常和引用的基本用途。
用可选值表示没有结果
「或可有」于「整数」 是可选整数类型。它有两种情况:「可有」于「值」 包含一个整数,「可无」 不包含结果。
下面的完整程序检查零除数,再分别处理成功和失败:
寻观「标准库」之书。
「安全除法」乃化「整数」而化「整数」而(「或可有」于「整数」)也。
「安全除法」者会「被除数」而会「除数」而
若「等」于「除数」于「零」
则「可无」
否则「可有」于(「除以」于「被除数」于「除数」)也。
「显示结果」乃化(「或可有」于「整数」)而「字符串」也。
「显示结果」者会「结果」而
鉴「结果」而
有「可无」则『除数不能为零。』
或有(「可有」于「商」)则「整数表示」于「商」也。
「打印行」于(「显示结果」于(「安全除法」于「八」于「二」))。
「打印行」于(「显示结果」于(「安全除法」于「八」于「零」))。
输出为:
4
除数不能为零。
安全除法负责计算并包装结果,显示结果负责决定怎样向用户说明。调用者不能直接把可选整数当作整数相加,需要先处理这两种情况。本例的“安全”仅指检查了零除数,使用固定宽度整数时仍需考虑数值范围。
什么时候使用异常
可选值把失败写进返回类型,适合查找不到、输入缺失等调用者预期会遇到的情况。如果程序发现无法在当前函数内继续处理的问题,可以通过 「发生事故」 抛出异常,例如:
「发生事故」于『配置内容无效』
这会中断当前正常执行路径。标准库的 「尝试运行」 接收一个待执行函数和一个异常处理函数,用来处理这种情况。异常不会像可选值那样要求每层调用都显式检查返回值,因此需要明确由哪一层负责处理。刚开始写程序时,优先把预期中的失败设计成返回值。
需要修改状态时使用引用
普通绑定不会被重新赋值。引用提供一个可以读取和写入的位置,适合保存需要逐步更新的状态。下面是独立的完整程序:
寻观「标准库」之书。
「计数器」乃「引用类」于「整数」也。
「计数器」者「新引用」授以「整数」于「零」也。
(「打印行」于(「整数表示」于(「读引用」授以「整数」于「计数器」));
(「写引用」授以「整数」于「计数器」于「一」);
「打印行」于(「整数表示」于(「读引用」授以「整数」于「计数器」)))。
输出依次是 0 和 1。「新引用」 创建位置,「读引用」 取出当前值,「写引用」 更新内容。名称 「计数器」 始终指向同一个引用,改变的是其中保存的整数。
这里给写引用的调用单独加了一对括号,明确带有 授以 的调用到哪里结束,再用分号连接下一个操作。
引用引入了执行顺序上的依赖,第二次读取的结果取决于前面的写入。如果只是传递中间计算结果,用第三章的局部绑定通常更直接。
练习
写一个函数把可选整数变成普通整数:有值就取出,没有值就返回零。用 可有(0) 和 可无 两种情况测试,结果都会是零。考虑这个默认策略是否符合调用者需要,还是应像本章程序一样保留失败说明。
上一章 · 下一章:完成一个列表处理程序 · 目录