这个函数作为一个典型的树递归是有指导意义的,但是它是一个计算斐波那契数的糟糕方法,因为它做了太多多余的计算。请注意图 1.5 中的[和](#c1-fig-0012)中的`fib(3)`的整个计算——几乎一半的工作——都是重复的。事实上,不难看出,函数将计算`fib(1)`或`fib(0)`的次数(一般来说是上述树中的叶子数)恰恰是 Fib( n + 1)。为了了解这有多糟糕,我们可以展示 Fib( n )的值随着 n 呈指数增长。更准确地说(见练习 1.13),Fib( n )是最接近 ϕ ^n / ![c1-fig-5009.jpg](img/c1-fig-5009.jpg)的整数,其中
我们将`and`实现为一系列查询的组合([图 4.6](#c4-fig-0006) )是优雅的,但它是低效的,因为在处理`and`的第二个查询时,我们必须扫描数据库以获得第一个查询产生的每一帧。如果数据库有 N 个元素,并且一个典型的查询产生与 N 成比例的输出帧的数量(比如说 N / k ),那么为第一个查询产生的每一帧扫描数据库将需要 N²/k 调用模式匹配器。另一种方法是分别处理`and`的两个子句,然后寻找所有兼容的输出帧对。如果每个查询产生 N / k 个输出帧,那么这意味着我们必须执行 N²/k²兼容性检查——比我们当前方法中所需的匹配数量少了 k 个因子。
我们将`and`实现为一系列查询的组合(图 4.6: )是优雅的,但它是低效的,因为在处理`and`的第二个查询时,我们必须扫描数据库以获得第一个查询产生的每一帧。如果数据库有 N 个元素,并且一个典型的查询产生与 N 成比例的输出帧的数量(比如说 N / k ),那么为第一个查询产生的每一帧扫描数据库将需要 N²/k 调用模式匹配器。另一种方法是分别处理`and`的两个子句,然后寻找所有兼容的输出帧对。如果每个查询产生 N / k 个输出帧,那么这意味着我们必须执行 N²/k²兼容性检查——比我们当前方法中所需的匹配数量少了 k 个因子。