I think higher order functions are the functional way to polymorphism: the same way you can write a generic algorithm in an OO language referring to an interface, which you can plug specific behaviour into the generic algorithm through, you can follow the same “plug something specific into something generic“ advice writing a high order function referring to a function signature.
Put it another way, function signatures are the functional counterpart for OO interfaces.
This is a very simple concept having big implications about you can design and organize your code. So, I think the best way to metabolize this concept is to get your hands dirty with higher order functions, in order to become faimilar with thinking in terms of functions that consume and return (other) functions.
For example, you can try to reimplement simple higher order functions from some library like lodash, ramdajs or similar. What about implementing an after
function that receives an integer n
and another function f
and returns a new function that invokes f
when it is invoked for the n
-th time?
1 | function after(n, f) { |
You can use like this:
1 | const counter = after(5, () => console.log('5!')) |
So you have a simple tool for count events, reacting to the n
-th occurrence (and you honored the Single Responsibility Principly, too, separating counting responsibility from business behavior implemented by f
). Each invocation of after
creates a scope (more technically: a closure for subsequent executions of the returned function - the value of n
or of variables defined in the lexical scope of after
‘s invocation are nothing different from the instance fields you can use in your class implementing an interface.
Generalizing this approach, you can implement subtle variation of the after
function: you can for example write an every
function that returns a function that call the f
parameter of the every
invocation every n
times
1 | function every(n, f) { |
This is my way to see functional composition through higher order functions: another way to plug my specific, business-related behavior into e generic - higher order - piece of code, without reimplement the generic algorithm the latter implements.
Bonus track: what is the higher order behaviour implemented by the following function?
1 | function canYouGuessMyName (items, f) { |
Written with StackEdit.