I have a question regarding this article.
Between this code
function odds(n, p) {
if(n == 0) {
return 1
} else {
return (n / p) * odds(n - 1, p - 1)
}
}
and this code
(function(){
var odds1 = function(n, p, acc) {
if(n == 0) {
return acc
} else {
return odds1(n - 1, p - 1, (n / p) * acc)
}
}
odds = function(n, p) {
return odds1(n, p, 1)
}
})()
1) I’m confused about how much this helps. Does the second snippet simply have a tail call that creates less overhead because it calculates what it needs before it calls itself again, or is there something more I’m missing?
As I understand it, the tail call still isn’t eliminated, just optimized.
2) And why does there need to be odds and odds1 anyway? It still isn’t clear to me either.
If the end of a procedure looks like this:
Then the compiler can optimize that away to just
Eliminating the procedure call entirely.
The "contract" of
oddsspecifies only two arguments – the third argument is just an implementation detail. So you hide that away in an internal method, and present a "wrapper" as the external API.You could call
odds1something likeoddsImpland it would make it clearer, I think.