Chapter 25 Syntax of a function: function()

function_name <- function(argument1, argument2, ...) {
  body  # What we want the function to do
  return(values)  # Optional
}
  • function_name is the name of the function, and will be stored in the R environemnt as an object with this name;
  • arguments take the defined values that can be used within the function;
  • body contains the statements that define what the function does;
  • output contains the returned value from the function. If return() is absent, then the last expression is returned.

25.1 Arguments of a function()

function_name <- function(argument1, argument2, ...) {
  body  # What we want the function to do
  return(values)  # Optional
}

Arguments are the input values of your function and will have the information your function needs to be able to perform correctly.

A function can have between zero and an infinity of arguments. See the following example:

operations <- function(number1, number2, number3) {
    result <- (number1 + number2) * number3
    print(result)
}
operations(1, 2, 3)
## [1] 9

Challenge 4

Using what you learned previously on flow control, create a function print_animal() that takes an animal as argument and gives the following results:

Scruffy <- "dog"
Paws <- "cat"
print_animal(Scruffy)
## [1] "woof"
print_animal(Paws)
## [1] "meow"

Challenge 4: Solution

Using what you learned previously on flow control, create a function print_animal() that takes an animal as argument and gives the following results:

Scruffy <- "dog"
Paws <- "cat"
print_animal(Scruffy)
## [1] "woof"
print_animal(Paws)
## [1] "meow"
print_animal <- function(animal) {
    if (animal == "dog") {
        print("woof")
    } else if (animal == "cat") {
        print("meow")
    }
}

25.2 Default argument values in a function

Arguments can be provided with a default value, or even be optional.

Default values are useful when using a function with the same settings. The flexibility to depart from default values is still there, if needed.

operations <- function(number1, number2, number3 = 3) {
    result <- (number1 + number2) * number3
    print(result)
}
operations(number1 = 1, number2 = 2, number3 = 3)
## [1] 9
# is equivalent to
operations(1, 2)
## [1] 9
operations(1, 2, 2)  # we can still change the value of number3 if needed
## [1] 6

25.3 The ellipsis argument: ...

The special argument ... allows you to pass arguments from other undefined functions, i.e. allowing for an indefinite number of arguments inputs.

paste_anything_fun <- function(...) {
    arguments <- list(...)
    paste0(arguments)
}
paste_anything_fun("I", "want", "a break!")
## [1] "I"        "want"    
## [3] "a break!"
percentages <- function(x, mult = 100, ...) {
    percent <- round(x * mult, ...)
    paste(percent, "%", sep = "")
}
percentages(c(0.543, 0.534, 0.466))
## [1] "54%" "53%" "47%"
# ?round
percentages(c(0.543, 0.534, 0.466), digits = 2)
## [1] "54.3%" "53.4%" "46.6%"

The special argument ... allows you to pass on arguments to another function used inside your function. Here we use ... to pass on arguments to plot() and points().

plot.CO2 <- function(CO2, ...) {
    plot(x = CO2$conc, y = CO2$uptake, type = "n", ...)
    for (i in 1:length(CO2[, 1])) {
        if (CO2$Type[i] == "Quebec") {
            points(CO2$conc[i], CO2$uptake[i], col = "red", type = "p",
                ...)
        } else if (CO2$Type[i] == "Mississippi") {
            points(CO2$conc[i], CO2$uptake[i], col = "blue",
                type = "p", ...)
        }
    }
}
plot.CO2(CO2, cex.lab = 1.2, xlab = "CO2 concentration", ylab = "CO2 uptake")
plot.CO2(CO2, cex.lab = 1.2, pch = 20, xlab = "CO2 concentration",
    ylab = "CO2 uptake")

25.4 Return values

The last expression evaluated in a function becomes the return value:

myfun <- function(x) {
    if (x < 10) {
        0
    } else {
        10
    }
}
myfun(5)
## [1] 0
myfun(15)
## [1] 10

function() itself returns the last evaluated value even without including return()

25.5 Return values

.small[ It can be useful to explicitly return() if the routine should end early, jump out of the function and return a value.

simplefun1 <- function(x) {
    if (x < 0)
        return(x)
}


Functions can return only a single object (and text). But this is not a limitation because you can return a list containing any number of objects.

simplefun2 <- function(x, y) {
    z <- x + y
    return(list(result = z, x = x, y = y))
}


simplefun2(1, 2)
## $result
## [1] 3
## 
## $x
## [1] 1
## 
## $y
## [1] 2

25.6 Challenge

Using what you have just learned on functions and control flow, create a function named bigsum that takes two arguments a and b and:

  1. Returns \(0\) if the sum of a and b is strictly less than \(50\);
  2. Else, returns the sum of a and b.

Challenge 5: Solution

Using what you have just learned on functions and control flow, create a function named bigsum that takes two arguments a and b and:

  1. Returns 0 if the sum of a and b is strictly less than 50;
  2. Else, returns the sum of a and b.

Answer 1

bigsum <- function(a, b) {
    result <- a + b
    if (result < 50) {
        return(0)
    } else {
        return(result)
    }
}

Answer 2

bigsum <- function(a, b) {
    result <- a + b
    if (result < 50) {
        0
    } else {
        result
    }
}