# Simplest function
f <- function(){}
f() # returns NULL because it does nothingNULL
Creating Functions and Understanding Scope in R
So far, we’ve been using R functions as tools.
Now, you’ll learn how to create your own.
A function in R is a reusable set of instructions that can take inputs (arguments), perform actions, and return outputs (results).
You’ll also learn about scope: the idea of where variables “live” inside or outside functions.
By the end of this module, you’ll be able to:
Creating a function is just like creating any other R object: you give it a name and assign it a value. This is also referred to as defining a function. To use this function we call or execute the function by writing its name, followed by parenthesis. ().
# Simplest function
f <- function(){}
f() # returns NULL because it does nothingNULL
A function is an object like any other variable in R. Since R is dynamically typed we are free to redefine f:
f <- 10
f # f is now numeric, not a function[1] 10
You can redefine it anytime:
f <- function(){}A function performs whatever expressions you include inside {}.
f <- function(){
"Hello, world!"
}
f()[1] "Hello, world!"
If no explicit return() is used, the last evaluated expression is returned automatically. Notice that the item returned is printed too unless you assign it to a variable
f <- function(){
"Hello, world!"
}
val <- f()or use invisible:
f <- function(){
invisible("Hello, world!")
}
f()To stop early or specify what to explicitly return, use return():
f <- function(){
return("AHHH!")
"Hello, world!"
}
f()[1] "AHHH!"
A function can both print and return values, but they are different.
[1] "AHHH!"
[1] "Hello, world!"
print() sends output to the console.return() (or the last expression) sends a value back to R for later use.
What’s been returned can be stored in a variable for later use:
Each function creates its own small environment where variables can exist locally.
Variables defined outside a function are global. In this example, f and a are global.
a <- 1
f <- function(){
b <- 2
print(b)
}
f() # f is being called and local variables are created[1] 2
Here, b exists only while f() runs and it’s local to the function.
You can also define local variables as parameters:
a <- 1
f <- function(b){
print(b)
}
f(2)[1] 2
Inside f(), b is local. It disappears after the function finishes.
If a variable isn’t found inside a function, R looks in the global environment:
a <- 1
f <- function(b){
print(a + b)
}
f(2)[1] 3
We don’t usually code this way — by accessing variables we expect might live out of the function in the global scope. There is an exception for functions. Because functions are defined globally, this allows us to use them inside other functions.
add_one <- function(a){
a + 1
}
f <- function(b){
add_one(b)
}
f(2)[1] 3
If you want to modify a, you are not able to by default. When a is assigned to inside the function definition it creates another local a that’s different from the global a.
a <- 1
f <- function(b){
a <- a + b # modifies a local copy
print(b)
}
f(2)[1] 2
a # unchanged[1] 1
To change the global variable, you can use <<-:
a <- 1
f <- function(b){
a <<- a + b
}
f(2)
a[1] 3
This works but can make debugging difficult.
A better practice is to return the new value and reassign it:
f <- function(a, b){
a <- a + b
return(a)
}
a <- f(a, 2)
a[1] 5
Answer the following for each example:
a <- 10
f <- function() {
b <- 2
print(a + b)
}
f()Global: a is 10, f is a function Local: b is 2.
Output: 12.
a <- 5
f <- function(a) {
b <- 2
print(a + b)
}
f(10)Global: a is 5, f is a function Local: a is 10, b is 2.
Output: 12.
Global: a is 1, f is a function Local: a is 4, b is 3.
Output: 4 and then 1.
f <- function(x) {
y <- x + 1
print(y)
y * 2
}
z <- f(3)
zGlobal: f is a function, z is 8. Local: x is 3, y is 4.
Output: 4 and then 8.
g <- function(x) {
y <- x^2
invisible(y)
}
w <- g(5)Global: g is a function, w is 25. Local: x is 5, y is 25.
Output: None