替换推理与记忆化
什么是引用透明?
- 引用透明: 表达式可直接替换为它的值,程序行为仍不改变;
- 示例: 若
greet()永远返回同一字符串,任意调用都可换成该字符串; - 破坏因素: 外部配置、数据库结果、时间等隐藏依赖;
const greet = () => "Hello World!";
// greet() 可替换为 'Hello World!'
等式推理怎样从局部推出整体?
- 前提: 程序由表达式组成且没有副作用;
- 方法: 使用纯度、结合律、交换律、幂等等局部性质推导组合后的性质;
const grainToDogs = compose(chickenIntoDogs, grainIntoChicken);
const grainToCats = compose(dogsIntoCats, grainToDogs);
- 若各组成函数纯,组合仍纯;无需运行整个系统才能确认这一点;
记忆化为什么要求纯函数?
- 记忆化: 按输入缓存函数返回值,重复输入直接复用缓存;
- 安全条件: 相同参数必须始终产生相同结果,且跳过执行不能漏掉副作用;
- 因此: 纯度与引用透明是安全记忆化的基础;
const memoize = (fn) => {
const cache = new Map();
return (arg) => {
if (!cache.has(arg)) cache.set(arg, fn(arg));
return cache.get(arg);
};
};
const factorial = memoize((n) => (n <= 1 ? 1 : n * factorial(n - 1)));
factorial(5); // 计算并缓存 120
factorial(5); // 直接读取 120
三个概念如何串联?
纯函数 → 引用透明 → 可用等式替换推理
↘ 可按输入安全记忆化