Module 2: Functional programming II Flashcards
Decorators, Currying, Partial, Closures
What are useful applications of higher-order functions?
- Function composition
- Decorators
- Currying
- Partial
- Closures
What are Decorators?
Decorators take an existing function and add some functionality (or “decoration”) over it
What is this code exemplifying?
def make_polite(func):
def inner():
print(“Hello, world! “,)
func()
return inner
@make_polite
def another_function():
print(“I am some other ordinary
function.”)
Decorator
The code is an example of a DECORATOR because it wraps another function (another_function
) to modify its behavior without changing its code. The make_polite
function adds a greeting before the original function’s output. Using @make_polite
applies this modification, demonstrating a decorator’s purpose: to extend or alter a function’s behavior dynamically.
When you apply @make_polite to another_function, another_function gets wrapped by inner. Therefore, calling another_function() now actually calls inner(), which in turn does two things:
Prints “Hello, world!”
Calls the original another_function() content, printing “I am some other ordinary function.”
Does a decorator modify the internal code of a function?
No, decorators add functionality but DON”T change the internal code of a functions thanks to function composition.
new function = decorator (original_function)
Original function is not changed and we keep the same interface.
Why are decorators useful?
Useful to maintain and augment existing code that is already working!
What are the phases when using decorators? Explain.
- Wrap: at definition time, the decorator takes the original function and returns
a new wrapped function - Evaluate: at evaluation time, the wrapping function usually calls the original
function. The wrapping function can pre-process the argument values or
post-process the return value (or both)
What are some common scenarios in which decorators are useful?
- Logging
- Security
- Handling incomplete data
How could you rewrite this multi-argument function?
f(a,b,c) = x
h = g(a)
i = h(b)
j = i(c) = x
or more compactly:
g(a)(b)(c)
What is currying?
The process of turning multi-argument functions into a composition of single argument functions
What is the natural way to implement currying?
Using decorators to add curry to the function
What does currying allow us to do?
- Look at the intermediate steps of a function
- Create specialized functions
What does currying rely on?
Function composition
Why is currying interesting from a functional programming perspective?
- by separating one complex multi-argument function into single argument functions,
we have simpler components: functions only have one input and one output - functions are compatible with theoretical frameworks that only allow single argument
functions (e.g. lambda calculus)
What does Partial do?
With partial, we can call multi-argument functions with less arguments than they require, and obtain a specialized function with fixed arguments.
What does Partial return?
Partial may return a (possibly multi-argument) function, or value