问题描述
我正在尝试使用memoization来优化Fibonacci函数的显式自递归实现。下面是相当标准的实现(一个简单且相当天真的实现,但关注实际问题)。
I'm trying to use memoization to optimize an explicitly self recursive implementation of the Fibonacci function. The implementation which is fairly standard (a simple and rather naïve implementation though to focus on the actual problem) follows.
Function.prototype.memoize = function () {
var originalFunction = this,
slice = Array.prototype.slice;
cache = {};
return function () {
var key = slice.call(arguments);
if (key in cache) {
return cache[key];
} else {
return cache[key] = originalFunction.apply(this, key);
}
};
};
现在,按照以下方式创建和记忆函数时,这可以 。 (情景1)
Now, when creating and memoizing a function as follows, this works. (Scenario 1)
var fibonacci = function (n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}.memoize();
console.log(fibonacci(100));
但是,以下情况不会。 (场景2) )
However, the following does not. (Scenario 2)
var fibonacci = function (n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};
console.log(fibonacci.memoize()(100));
这两者都没有。 (场景3)
function fibonacci(n) {
return n === 0 || n === 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci.memoize()(100));
我的假设是因为调用 memoize()的方式不同/ code>关于函数,有些东西正在改变。请注意,功能在其他方面是相同的。我想这可能是因为除了第一个例子之外,只有第一个电话被记忆,而不是递归电话。
问题
如果我的上述假设确实正确,那为什么会发生这种情况?有人可以详细解释后两种情况与第一种情况有何不同吗?
If my supposition above is indeed correct, then why is this happening? Can someone explain in detail how the latter two scenarios differ from the first?
在这种情况下工作意味着返回第100个Fibonacci数,因为只有在使用memoization的情况下才可以递归计算它。
To work in this instance means to return the 100th Fibonacci number since it is only possible to compute it recursively if memoization is used.
不工作是崩溃浏览器。
To not work is to crash the browser.
推荐答案
是的,只有第一个呼叫在第二个呼叫被记忆,第三种情况。
Yes, it's right that only the first call is memoized in the second and third scenarios.
在第一种情况下,对原始函数的引用仅作为值存在,然后 memoize
是应用于此和斐波那契
变量包含对memoized函数的引用。
In the first scenario the reference to the original function only exists as a value, then memoize
is applied to that and the fibonacci
variable contains the reference to the memoized function.
在第二和第三个场景中 fibonacci
是对原始函数的引用。包含对memoized函数的引用的表达式 fibonaci.memoize()
的值仅在调用一次之前作为值存在。
In the second and third scenario fibonacci
is a reference to the original function. The value of the expression fibonaci.memoize()
that contains the reference to the memoized function only exist as a value before it is called once.
memoize
方法不会更改原始函数,而是返回一个包装原始函数的新函数。原始函数没有变化,要使用memoization,你必须调用 memoize
方法返回的函数。
The memoize
method doesn't change the original function, instead it returns a new function that wraps the original function. The original function is unchanged, and to use the memoization you have to call the function returned by the memoize
method.
在函数对 fibonacci
进行递归调用的第一个场景中,它是使用的memoized函数。在进行递归调用的第二个和第三个场景中, fibonacci
是原始函数。
In the first scenario when the function makes a recursive call to fibonacci
, it's the memoized function that is used. In the second and third scenarios when the recursive call is made, fibonacci
is the original function instead.
这篇关于为什么这个memoization实现可以在匿名函数上工作,但不能在声明的函数上工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!