6

I do understand that higher-order functions are functions that take functions as parameters or return functions. I also know that decorators are functions that add some functionality to other functions. What are they exactly? Are they the functions that are passed in as parameters or are they the higher-order functions themselves?

Note: If you give an example, use python.

Benji
  • 45
  • 8
blobodep
  • 119
  • 1
  • 7
  • Decorators are higher-order functions with a peculiar syntax and a specific purpose. – molbdnilo Jun 11 '20 at 16:13
  • 1
    Does this answer your question? [How to make a chain of function decorators?](https://stackoverflow.com/questions/739654/how-to-make-a-chain-of-function-decorators) Although this is about chaining decorators, the second answer is the broadest one you will find on decorators (also basic ones) – Tomerikoo Jun 11 '20 at 16:16
  • A decorator accepts a function and returns a function. It might even have one more level of indirection, for a decorator with parameters. – bipll Jun 11 '20 at 16:23

2 Answers2

12

A higher order function is a function that takes a function as an argument OR* returns a function.

A decorator in Python is (typically) an example of a higher-order function, but there are decorators that aren't (class decorators**, and decorators that aren't functions), and there are higher-order functions that aren't decorators, for example those that take two required arguments that are functions.

Not decorator, not higher-order function:

def hello(who):
    print("Hello", who)

Not decorator, but higher-order function:

def compose(f, g):
    def wrapper(*args, **kwargs):
        return g(f(*args, **kwargs))
    return wrapper

Decorator, not higher-order function:

def classdeco(cls):
    cls.__repr__ = lambda self: "WAT"
    return cls

# Usage:
@classdeco
class Foo:
    pass

Decorator, higher-order function:

def log_calls(fn):
    def wrapper(*args, **kwargs):
        print("Calling", fn.__name__)
        return fn(*args, **kwargs)
    return wrapper

* Not XOR
** Whether or not you consider class decorators to be higher-order functions, because classes are callable etc. is up for debate, I guess..

L3viathan
  • 26,748
  • 2
  • 58
  • 81
  • what is that g in not decorator but higher order function. – blobodep Jun 11 '20 at 16:22
  • 2
    There's really no such thing as "a decorator". Decorator syntax is just a shortcut for applying a function `f` to a function `g` immediately after `g` is defined, and rebinding the name `g` to the result of `f`. `f` can do anything it wants. – chepner Jun 11 '20 at 16:24
  • @blobodep You can't use `compose` with the decorator syntax, because a decorator (when used with the special syntax) always takes exactly one argument. – L3viathan Jun 11 '20 at 16:25
  • @chepner Of course there is a thing such as a decorator, but as usual in Python, it's not a specific type, but a more flexible contract-based thing, same as with "file-like objects" etc. A decorator is anything you can use following the `@` in the decorator syntax. – L3viathan Jun 11 '20 at 16:26
  • if anyone is confused, OR* that says not XOR* means a higher order function can take a function, or return a function or both. This is a logical OR xD – maininformer May 04 '21 at 21:55
4

A higher-order function is a function that either takes a function as an argument or returns a function.

Decorator syntax is a syntactic shortcut:

@f
def g(...):
    ...

is just a convenient shorthand for

def g(...):
    ...
g = f(g)

As such, a decorator really is simply a function that takes another function as an argument. It would be more accurate to talk about using f as a decorator than to say that f is a decorator.

chepner
  • 497,756
  • 71
  • 530
  • 681