(I added some console.log lines so you can get a better visualization of what's happening. You wouldn't want to leave these in your code.)
function add1 (x, k) {
k (x + 1)
}
function sub1 (x, k) {
k (x - 1)
}
function addk (x, y, k) {
console.log('adding:', x, y)
if (y === 0)
k (x)
else
add1 (x, function (x1) {
sub1 (y, function (y1) {
addk (x1, y1, k)
})
})
}
function multk (x, y, k) {
function aux (result, counter, k) {
console.log('multiplying:', result, counter)
if (counter === 0)
k (result)
else
addk (result, x, function (result1) {
sub1 (counter, function (counter1) {
aux (result1, counter1, k)
})
})
}
aux (0, y, k)
}
multk (5, 4, function (result) { console.log('result:', result) /* 20 */ })
function add1 (x, k) {
k (x + 1)
}
function sub1 (x, k) {
k (x - 1)
}
function addk (x, y, k) {
console.log('adding:', x, y)
if (y === 0)
k (x)
else
add1 (x, function (x1) {
sub1 (y, function (y1) {
addk (x1, y1, k)
})
})
}
function multk (x, y, k) {
function aux (result, counter, k) {
console.log('multiplying:', result, counter)
if (counter === 0)
k (result)
else
addk (result, x, function (result1) {
sub1 (counter, function (counter1) {
aux (result1, counter1, k)
})
})
}
aux (0, y, k)
}
multk (5, 4, function (result) { console.log(result) /* 20 */ })
(I added some console.log lines so you can get a better visualization of what's happening. You wouldn't want to leave these in your code.)
function add1 (x, k) {
k (x + 1)
}
function sub1 (x, k) {
k (x - 1)
}
function addk (x, y, k) {
console.log('adding:', x, y)
if (y === 0)
k (x)
else
add1 (x, function (x1) {
sub1 (y, function (y1) {
addk (x1, y1, k)
})
})
}
function multk (x, y, k) {
function aux (result, counter, k) {
console.log('multiplying:', result, counter)
if (counter === 0)
k (result)
else
addk (result, x, function (result1) {
sub1 (counter, function (counter1) {
aux (result1, counter1, k)
})
})
}
aux (0, y, k)
}
multk (5, 4, function (result) { console.log('result:', result) /* 20 */ })
Great answers from @torazaburo and @nnnnnn – they're practical and should solve your immediate problem. I'll offer some other alternatives in hope that these will help your brain think about recursive procedures in a variety of ways.
Another common recursion technique is using state variables in an auxiliary function
function mult (x, y) {
function aux (result, counter) {
if (counter === 0)
return result
else
return aux (result + x, counter - 1)
}
return aux (0, y)
}
console.log(mult (5, 4)) // 20
Here's another technique that uses continuation passing style
function multk (x, y, k) {
if (y === 0)
k (0)
else
multk (x, y - 1, function (result) { k (result + x) })
}
multk (5, 4, function (result) { console.log(result) /* 20 */ })
And here's a nutty boiled down version that uses nothing more than primitive +1 and primitive -1. It may seem complicated but I constructed it for you so that you can see how more complex recursive procedures can be built out of smaller ones. If you can follow this code, it should help you gain a greater understanding of recursion.
function add1 (x) {
return x + 1
}
function sub1 (x) {
return x - 1
}
function add (x, y) {
console.log('adding:', x, y)
if (y === 0)
return x
else
return add (add1(x), sub1(y))
}
function mult (x, y) {
function aux (result, counter) {
console.log('multiplying:', result, counter)
if (counter === 0)
return result
else
return aux (add(result, x), sub1(counter))
}
return aux (0, y)
}
console.log('result:', mult (5, 4)) // 20
And the same thing using undelimited continuations
function add1 (x, k) {
k (x + 1)
}
function sub1 (x, k) {
k (x - 1)
}
function addk (x, y, k) {
console.log('adding:', x, y)
if (y === 0)
k (x)
else
add1 (x, function (x1) {
sub1 (y, function (y1) {
addk (x1, y1, k)
})
})
}
function multk (x, y, k) {
function aux (result, counter, k) {
console.log('multiplying:', result, counter)
if (counter === 0)
k (result)
else
addk (result, x, function (result1) {
sub1 (counter, function (counter1) {
aux (result1, counter1, k)
})
})
}
aux (0, y, k)
}
multk (5, 4, function (result) { console.log(result) /* 20 */ })