What is higher order function ?
Functions that operate on other functions, either by taking them as
arguments or by returning them, are called higher-order functions.
Let me start with a small example and then we get back to the problem in the question.
function evenNumberFilter(number) {
return number%2==0
}
function oddNumberFilter(number) {
return !evenNumberFilter(number)
}
evenNumberFilter(2) // true
oddNumberFilter(3) // true
Now we know if we call function
evenNumberFilter
with parameter X
it will return true
if it is even number
oddNumberFilter
with parameter X
it will return true
if it is odd number
Let's extend the problem and say
"I would like to have all even numbers till number 10"
"I would like to have all odd numbers till number 10"
function evenNumberFilter(number) {
return number %2 == 0
}
function oddNumberFilter(number) {
return !evenNumberFilter(number)
}
function evenNumberBeforeTen() {
const result = []
for(number=0; number<10; number++) {
if (evenNumberFilter(number)) {
result.push(number)
}
}
return result
}
function oddNumberBeforeTen() {
const result = []
for(number=0; number<10; number++) {
if (oddNumberFilter(number)) {
result.push(number)
}
}
return result
}
evenNumberBeforeTen(); //[0,2,4,6,8]
oddNumberBeforeTen(); //[1,3,5,7,9]
If we look at the code both evenNumberBeforeTen
and oddNumberBeforeTen
share good amount of common code
- The way for loop is itereated
- The way result is appended to an array
- The result that is returned at the end of the function.
Only difference between these two functions is, what filter
it operates on either evenNumberFilter
or oddNumberFilter
.
So can we refactor the code and write one generic filter
function which can take the predicate as a parameter ?
Predicate: a boolean-valued function P: X? {true, false}
.
In our case both evenNumberFilter
and oddNumberFilter
are
predicates
function evenNumberFilter(number) {
return number %2 == 0
}
function oddNumberFilter(number) {
return !evenNumberFilter(number)
}
function filter(predicate) {
const result = []
for(number=0; number<10; number++) {
if (predicate(number)) {
result.push(number)
}
}
return result
}
filter(evenNumberFilter); //[0,2,4,6,8]
filter(oddNumberFilter); //[1,3,5,7,9]
Now, in the above example function filter
is higher order function because it takes function predicate
as parameter.
Let's get into the problem you mentioned in the question.
repeat
is a higher order function which takes number
and function action
as a parameter.
unless
is a higher order function which takes boolean
and function then
as a parameter
When you execute
repeat(3, n => {
unless(n%2 == 1, () => {
console.log(`${n} is even`);
});
});
repeat
is called first and then it will execute function below 3 times.
function (n) => {
unless(n%2 == 1, () => {
console.log(`${n} is even`);
});
- When above function is called with parameters 0,1,2. It calls
unless
function with boolean of n%2==1
which will be either true
or false
and function below as parameter.
function() => {
console.log(`${n} is even`);
});
When unless is called with true
and then
it will not execute the then
function so no log is printed
When unless is called with false
and then
it will execute the then
function which prints the log