Higher-Order Functions

Published:

Higher-order function is a function that takes a function as a parameter or returns a function [1]. There may be multiple functions given as arguments.

An simple use:

def prepare_seats(seats: int, allocate_seats: typing.Callable) -> int:
    """
    Returns the number of seats prepared.
    """
    if seats > 10:
        return allocate_seats(seats)
    return prepare_table(seats)

or

def get_booking_function(service: str) -> typing.Callable:
    """Returns a function for booking different services."""
    service_type: str = type(service)
    if service_type == 'restaurant':
        return book_restaurant_table
    elif service_type == 'hotel':
        return book_hotel_room
    raise ServiceDoesNotExist

React Controlled Input Example

I like using these kind of structures because it simplifies repetitive code. For example in React form we would "normally" do

const BookingForm = props => {
  const [formData, setFormData] = useState({
    tableNumber: "",
  })
  const handleChange = event => {
    setFormData({
      ...formData,
      [event.target.id]: getInputValue(event),
    })
  }
}

Instead of always copying and pasting the handleChange, it is easier to use a higher-order-function to get the function.

const BookingForm = props => {
  const [formData, setFormData] = useState({
    tableNumber: "",
  })
  const handleChange = useHandleChange(formData, setFormData)
}

Theme ClassName Example

It is often needed to construct className string if not using css-in-js.

/** Returns a function to build classNames with prefix. */
function useClassName(libraryPrefix) {
  return classNames => {
    classNames.map(className => `${libraryPrefix}${className}`)
  }
}

That kind of use case is handy when we have several styles with different prefixes such as in color themes light and dark in those cases we can do it as

const getClassName = useClassName("light--")
getClassName("button primary")
// light--button light--primary

const getClassName = useClassName("dark--")
getClassName("button primary")
// dark--button dark--primary

If one is not aware of higher-order-functions it may be tempted to write it as

<button className={`${theme}--button ${theme}--primary`} />

whereas it is simpler to write

<button className={getClassName(["button", "primary"])} />

In few classes such as above writing theme directly could beat using function but when we have more classes it gets greatly shortened. It is also easier to modify by replacing the useClassName if flexibility is needed. For example, when we need to change from prefixed classnames to postfixed styles then we would have to rewrite all if explicitly declared but when using functions we can just modify the useClassName.

References

  1. https://eloquentjavascript.net/05_higher_order.html