2.6 Designed for Functional Programming

Functional Programming is an approach to replace iterative (i.e. for) loops. Consider the case where you may want two times the square root of the mpg for each car in mtcars. You could do this with a for loop as follows:

n <- nrow(mtcars)
roots <- rep(NA_real_, n)
for (car in 1:n) {
  roots[car] <- 2 * sqrt(mtcars$mpg[car])
}

You could also write a function to do the computations. In functional programming, it’s important that the function does not have any side effects and the output only depends on the inputs. For example, the function my_sqrt() takes in a car’s mpg and a weight by which to multiply the square root.

my_sqrt <- function(mpg, weight) {
  weight * sqrt(mpg)
}

Using the purrr package, we can forgo the for loop and use the map() family of functions which use the basic syntax of map(vector, function). Below, we are applying the my_sqrt() function, with a weight of 2, to the first three elements of mtcars$mpg. User supplied functions can be declared by prefacing it with ~ (pronounced “twiddle”).

  • By default, map() returns a list.

    • If you know the class of a function’s output, you can use special suffixes. A character output, for example, would used by map_chr(), a double by map_dbl(), and a logical by map_lgl().
map(
  .x = head(mtcars$mpg, 3),
  ~ my_sqrt(
    mpg = .x,
    weight = 2
  )
)
## [[1]]
## [1] 9.165151
## 
## [[2]]
## [1] 9.165151
## 
## [[3]]
## [1] 9.549869
  • map() functions can be used with 2 inputs, by specifying map2()

    • Requires arguments .x and .y
map2(
  .x = head(mtcars$mpg, 3),
  .y = c(1,2,3),
  ~ my_sqrt(
    mpg = .x,
    weight = .y
  )
)
## [[1]]
## [1] 4.582576
## 
## [[2]]
## [1] 9.165151
## 
## [[3]]
## [1] 14.3248