I was playing around with recursion and looking at the benchmark of different implementation.
function plusOne(xs) {
if (xs.length <= 0) return []
return [xs[0], ...plusOne(xs.slice(1))]
}
function plusOne2(xs) {
if (xs.length <= 0) return Promise.resolve([])
return plusOne2(xs.slice(1)).then(result => [xs[0] 1, ...result])
}
function plusOne3(xs, cb) {
if (xs.length <= 0) return cb([])
return plusOne3(xs.slice(1), result => cb([xs[0], ...result]))
}
I notice the performance improved in the second implementation when I simply wrap the result in promise. I wonder why would it be the case.
Also in the third implementation, shouldn't the browser be able to do tail call optimisation with this continuation passing style? Why is it the slowest instead?
CodePudding user response:
I notice the performance improved in the second implementation when I simply wrap the result in promise. I wonder why would it be the case.
Because you're not .then()
ing the promise to finally resolve its value, so the .then()
chain isn't called.
In other words: it's faster because it's not doing the work.
Also in the third implementation, shouldn't the browser be able to do tail call optimisation with this continuation passing style?
You assume your browser's JS engine can recognize it can do tail call optimisation there. For instance, what if your cb
would require information on the call stack?
CodePudding user response:
You are not waiting for those promises to finish.
Try this:
async function plusOne(xs) {
if (xs.length <= 0) return []
return [xs[0] 1, ... await plusOne(xs.slice(1))]
}
await plusOne(xs)