考虑函数f(x,y):
f(x,0) = x*x;
f(0,y) = y*(y + 1);
f(x,y) = f(x,y-1) + f(x-1,y);
如果试图以某种语言(如C ++)递归实现,那么他将遇到问题。
假设首先使用x = x0
和y = y0
调用该函数。然后对于任何对(x,y),其中0 <= x < x0
和0 <= y < y0
中间值将被多次计算 - 递归调用将形成一个巨大的树,其中多个叶子实际上将包含相同的对(x ,Y)。对于对(x,y),其中x和y都接近于0,将多次计算值。
例如,我测试了一个用C ++实现的类似函数 - 对于x=20
和y=20
,它的计算大约需要4个小时(是的,4个地球时间!)。
显然,可以通过迭代方式或缓存表不重复计算的方式重写实现。
问题是:在递归实现上述函数时,函数式语言是否会更好地执行并避免重复计算?
答案 0 :(得分:7)
您在这里寻找的术语是Memoization:
在计算中,memoization是一个 优化技术主要用于 加快计算机程序 有函数调用避免重复 计算结果 以前处理的输入。
不,功能语言不会自动实现memoization。您可以在它们中实现它,但也可以在C ++中实现它。但是,当你编写纯功能代码(即没有副作用)时,记忆就更容易了。一些动态语言(例如Perl)具有自动记忆模块,可以轻松记忆任何功能。 Automatic memoization section of the Wikipedia article中讨论了这个主题。
例如,这是一个天真的C ++ Fibonacci:
long fib_rec(long index)
{
if (index < 2)
return index;
else
return fib_rec(index - 1) + fib_rec(index - 2);
}
这是一个记忆版本:
long fib_memoized_aux(vector<long>& cache, long index)
{
if (cache[index] >= 0)
return cache[index];
cache[index] = fib_memoized_aux(cache, index - 1) + fib_memoized_aux(cache, index - 2);
return cache[index];
}
long fib_memoized(long index)
{
vector<long> cache(index + 1, -1);
cache[0] = 0;
cache[1] = 1;
return fib_memoized_aux(cache, index);
}