1.6 Anonymous Functions

Anonymous Functions

An anonymous function is a function without a name. In R, we create them using the function() syntax.

For example: I’ll create an anonymous function that doubles any number it receives. I’ll say the input is called x, but you could just as easily call the input y, z, z10, or elephant, as long as you’re consistent when you declare the function’s inputs and when you write the body of the function. Variable names in R should start with a letter, they can contain letters, numbers, dots, and underscores, and they cannot be reserved keywords like if, else, TRUE, or NULL.

function(x) 2 * x
function(x) 2 * x
# Test the function by wrapping the entire function in parentheses and then providing an input value:

(function(x) 2 * x)(x = 5)
[1] 10

In R, you can pass inputs (arguments) into functions by name or by position. So I can leave out the x = and the code still works, because it recognizes that the value 5 is being passed to the first and only argument of the function:

(function(x) 2 * x)(5)
[1] 10

1) Write an anonymous function that adds 10 to any number it receives. Test it with the input 3.

Functions that take vectors

Note that these functions can work on vectors too. Let’s test my function from the previous example on a vector to see if it doubles every element of the vector.

(function(x) 2 * x)(c(5, 4, 3))
[1] 10  8  6

2) Does your function from problem 1 work on vectors? Test it with the vector c(5, 4, 3).

Named Functions

Named functions are anonymous functions that we’ve assigned to a variable. For example, when you run the code below, the variable two_times refers to the function function(x) 2 * x in your global environment. You should see evidence of this in your environment tab (upper right hand pane). The assignment operator <- lets you assign something a variable name in the environment.

two_times <- function(x) 2 * x

Why bother saving a function to our global environment under a variable name? Doing this allows us to refer back to that function as many times as we want to evaluate it with different inputs:

two_times(10)
[1] 20
two_times(1000)
[1] 2000
two_times(1:10)
 [1]  2  4  6  8 10 12 14 16 18 20

3) Take your function from problem 1, assign it a variable name using the assignment operator <-, and evaluate that function on multiple inputs by referring to it using its variable name.

Answer:

# add_10 <- ___
# add_10(0)
# add_10(5)
# add_10(1:10)

4) Create a named function called calculate_range that takes a numeric vector as input, finds the difference between the maximum and the minimum values, and returns that difference. Test it on a vector.

More Details on Functions

Functions that return multiple values

In order to return multiple values, you need to make your function return a vector, a tibble, etc.

function(x) c(min(x), max(x), mean(x))
function(x) c(min(x), max(x), mean(x))
(function(x) c(min(x), max(x), mean(x)))(c(5, 3, 9))
[1] 3.000000 9.000000 5.666667

Functions with Bodies that Span Multiple Lines

When your function does something a little more complicated and you need to define a function body over multiple lines, you need to wrap your function body in curly brackets {}.

function(x) {
  minimum <- min(x)
  maximum <- max(x)
  average <- mean(x)
  c(minimum, maximum, average)
}
function(x) {
  minimum <- min(x)
  maximum <- max(x)
  average <- mean(x)
  c(minimum, maximum, average)
}

Notice here that when you evaluate this function, minimum, maximum, and average do NOT appear in your global environment even though you created variables using the assignment operator. That’s because they’re variables that are defined in the function environment when you evaluate the function, not in the global environment.

Using return statements

Return statements explicitly specify what the function should output. They’re optional in R because functions automatically return their last evaluated expression, but they can make code clearer or enable early returns (like in an if statement).

function(x) {
  y <- x^2
  z <- y + 1
  return(z)
}
function(x) {
  y <- x^2
  z <- y + 1
  return(z)
}

5) Create a function called summarize_vector that takes a numeric vector x and returns vector containing:

  • The length of the vector (call this x_len)
  • The sum of all values (call this x_sum)
  • The mean of all values (call this x_mean)

Use curly brackets and a return statement. Test it on the vector 1:5.

# ___ <- function(x) {
#   ___ <- ___
#   ___ <- ___
#   ___ <- ___
#   return(___) 
# }

# ___(1:5)