a HOF is just a function which takes a function as an argument. Alternatively, it’s a function which returns a new function. In both cases it’s a higher-order function. There is another case when you define a function which returns a function. This could be a middleware in Clojure’s Ring or a Python decorator:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_whee():
print("Whee!")
def do_twice(func):
def wrapper_do_twice(*args, **kwargs):
func(*args, **kwargs)
func(*args, **kwargs)
return wrapper_do_twice
@do_twice
def greet(name):
print(f"Hello {name}")
say_whee()
greet("World")
(defn some-hof [func]
(fn []
(println "Something is happening before the function is called.")
(func)
(println "Something is happening after the function is called.")))
(defn do-twice [func]
(fn [& args]
(apply func args)
(apply func args)))
(defn say-whee []
(println "Whee!"))
((some-hof say-whee))
((do-twice say-whee))
((->> say-whee do-twice some-hof))
I would argue that higher order functions are better as it doesn't mutate the original function, e.g. wrapping say-whee with two decorators rather than composing.