如果我定义一个函数
inc = function(x) { return x + 1 }
Run Code Online (Sandbox Code Playgroud)
并对其进行嵌套调用
inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(1)))))))))))))))))))))
Run Code Online (Sandbox Code Playgroud)
这将导致价值22.如果我修改嵌套表达式而不是使用call,传入nullfor this,as
inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, 1)))))))))))))))))))))
Run Code Online (Sandbox Code Playgroud)
这也将产生价值22.
但是,在JavaScriptCore上,第二种形式似乎消耗O(2 ^ n)内存,其中n是嵌套调用的数量.如果我在Firefox或Chrome中尝试使用此JavaScript,则情况并非如此,因此它似乎与JavaScriptCore隔离.
我的JavaScript经验非常少(几乎没有).我不了解各种JavaScript实现可能做出的权衡,也不了解示例代码在某些实现中是否合理(为闭包或某些实现提供通用支持),而在其他实现中是有效的.
我的问题是:这段代码本身存在问题吗?是否应该以不同的方式重写?或者代码很好 - JavaScriptCore只是有一个bug吗?
我做了一些实验,重构一些内部调用临时工作将"截断"内存倍增行为
var temp1 = inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, 1)))))));
var temp2 = inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, …Run Code Online (Sandbox Code Playgroud) 假设你有一个let块中定义的递归函数:
(let [fib (fn fib [n]
(if (< n 2)
n
(+ (fib (- n 1))
(fib (- n 2)))))]
(fib 42))
Run Code Online (Sandbox Code Playgroud)
这可以通过机械方式转换为利用memoize:
fn在打电话中包裹表格memoize.partial.转换上面的代码会导致:
(let [fib (memoize
(fn [fib n]
(if (< n 2)
n
(+ (fib fib (- n 1))
(fib fib (- n 2))))))
fib (partial fib fib)]
(fib 42))
Run Code Online (Sandbox Code Playgroud)
这有效,但感觉过于复杂.问题是:有更简单的方法吗?