Reputation: 45
I am really new to funcitonal paradigm and I have a hard time understanding what is going on with the following snippet.
const countDown = (val, cb, delay = 1000) => {
cb(val, delay);
return (val > 0) ? setTimeout(() => countDown(val - 1, cb, delay), delay) : val;
}
countDown(5, console.log, 100)
Why the following doesn't work, given the fact that setTimeout
takes a function as an argument?
const countDown = (val, cb, delay = 1000) => {
cb(val, delay);
return (val > 0) ? setTimeout(countDown(val - 1, cb, delay), delay) : val;
}
countDown(5, console.log, 100)
Upvotes: 1
Views: 463
Reputation: 135227
This is another way you can look at your problem. countDown
is concerned with repeatedly calling a function, decrementing a counter, and inserting some time in between the function calls – that's a lot for one function.
I'll be abstracting some of this complexity away with delay
and effect
and repeat
. You'll notice that countDown
requires zero logic once we've abstracted to this point – this is sometimes why people say functional programs can take on a declarative resemblance.
const delay = ms => x =>
new Promise (r => setTimeout (r, ms, x))
const effect = f => x =>
(f (x), x)
const repeat = n => f => x =>
n === 0 ? x : repeat (n - 1) (f) (f (x))
const countDown = (x, ms, f) =>
repeat (x)
(p => p.then (effect (f)) .then (delay (ms)) .then (x => x - 1))
(Promise.resolve (x))
countDown (5, 1000, console.log)
.then (x => console.log ('done', x))
Upvotes: 0
Reputation: 4858
The setTimeout
function takes a callback function as first argument. So in your example you need to pass a function definition and not the function call.
this is a function definition:
() => countDown(val - 1, cb, delay), delay)
or the same without arrow functions:
function() { countDown(val - 1, cb, delay), delay) }
while this is a function call:
countDown(val - 1, cb, delay)
Upvotes: 1