跳到主要内容

替换推理与记忆化

什么是引用透明?​

  • 引用透明: 表达式可直接替换为它的值,程序行为仍不改变;
  • 示例: 若 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

三个概念如何串联?​

纯函数 → 引用透明 → 可用等式替换推理
↘ 可按输入安全记忆化