Creating functions
The “function”
- The “function” function creates a function
mySum <- function(a, b) {
z <- a + b
return(z)
}
mySum(3,4)
## [1] 7
z
## Error in eval(expr, envir, enclos): object 'z' not found
# What happens to z?
# No explict return value
mySum <- function(a, b) {
a + b
}
mySum(5,10)
## [1] 15
# What if we assign the result to a variable?
mySum <- function(a, b) {
z <- a + b
}
mySum(5,10)
# Setting default values
mySum <- function(a = 0, b = 1) {
z <- a + b
return(z)
}
mySum(5, 10)
## [1] 15
mySum(5)
## [1] 6
mySum()
## [1] 1
mySum(b = 3, a = 1)
## [1] 4
Function components
- Body: Code inside the function
- Formals: The list of arguments
- The environment: Location of a function’s variables
mySum <- function(a = 0, b = 1) {
z <- a + b
return(z)
}
body(mySum)
## {
## z <- a + b
## return(z)
## }
formals(mySum)
## $a
## [1] 0
##
## $b
## [1] 1
environment(mySum)
## <environment: R_GlobalEnv>
sumNA <- function(...) {
return(sum(..., na.rm = TRUE))
}
body(sumNA)
## {
## return(sum(..., na.rm = TRUE))
## }
formals(sumNA)
## $...
environment(sumNA)
## <environment: R_GlobalEnv>
aa <- c(1, 3, NA, 4)
sum(aa)
## [1] NA
sumNA(aa)
## [1] 8
Primitive functions
- Base R functions
- Coded in C
sum
## function (..., na.rm = FALSE) .Primitive("sum")
body(sum)
## NULL
formals(sum)
## NULL
environment(sum)
## NULL
Name masking
a <- 10
b <- 100
f1 <- function() {
a <- 1
b <- 2
sum(a + b)
}
f2 <- function() {
b <- 2
sum(a + b)
}
f1()
## [1] 3
f2()
## [1] 12
f3 <- function(a = 1) {
b <<- a * 5
d <<- 10
e <- 20
}
a
## [1] 10
b
## [1] 100
d
## Error in eval(expr, envir, enclos): object 'd' not found
e
## Error in eval(expr, envir, enclos): object 'e' not found
f3()
a
## [1] 10
b
## [1] 5
d
## [1] 10
e
## Error in eval(expr, envir, enclos): object 'e' not found
Functions within functions
exp <- function(a = 1) {
function(x) {
x^a
}
}
mySq <- exp(2)
myCube <- exp(3)
mySq
## function(x) {
## x^a
## }
## <environment: 0x55a97369aaa8>
mySq(9)
## [1] 81
myCube(2)
## [1] 8
Lazy evaluation
- Functions’ arguments are evaluated when they are used
f1 <- function(a = 10, b = d) {
d <- (a + 1) ^ 2
return(a + b)
}
f1()
## [1] 131
f1(1)
## [1] 5
f1(1, 5)
## [1] 6
- Conditional argument creation
f1 <- function(a = 1, b) {
if (missing(b)) b = (a + 1) ^ 2
return(a + b)
}
f1()
## [1] 5
f1(1)
## [1] 5
f1(1, 5)
## [1] 6
f1 <- function(x) {
10
}
f1(stop("This is an error!"))
## [1] 10
f1 <- function(x) {
force(x)
10
}
f1(stop("This is an error!"))
## Error in force(x): This is an error!
Special functions
- Infix functions
- Function name comes in between its arguments
`%pow%` <- function(a, b) {a^b}
2 %pow% 3
## [1] 8
- Every operation is a function!
# Sum operator
`+`
## function (e1, e2) .Primitive("+")
`+` <- function(a, b) {a - b}
2 + 2
## [1] 0
`+` <- function(a, b) {a + b}
- Replacement functions
- They modify their “arguments”
- Special name: “fname <-”
`modify<-` <- function(x, position, value) {
x[position] <- value
x
}
x <- c(1:10)
x
## [1] 1 2 3 4 5 6 7 8 9 10
modify(x, 1) <- 10
x
## [1] 10 2 3 4 5 6 7 8 9 10
Loops in R
a <- c(1:10)
b <- sample(10, 10)
a
b
d <- NULL
# for loop
for (i in c(1:10)) {
d[i] <- a[i] + b[i]
}
d
# while loop
while ( i < 11) {
d[i] <- a[i] * b[i]
i <- i + 1
}
d
# repeat loop
aa <- 1
while (aa != 0) {
aa <- as.numeric(readline(prompt="Please, enter your a number: "))
cat("Square of ", aa, " is equal to ", aa^2)
}
a <- c(1:10)
b <- sample(10, 10)
a
b
d <- NULL
# for loop
for (i in c(1:10)) {
d[i] <- a[i] + b[i]
}
d
# while loop
while ( i < 11) {
d[i] <- a[i] * b[i]
i <- i + 1
}
d
# repeat loop
aa <- 1
while (aa != 0) {
aa <- as.numeric(readline(prompt="Please, enter your a number: "))
cat("Square of ", aa, " is equal to ", aa^2)
}
# Time
a <- sample(100, 10000000, replace = TRUE)
b <- sample(100, 10000000, replace = TRUE)
sumAB <- 0
system.time(for (i in c(1:length(a))) {
sumAB <- sumAB + (a[i] < b[i])
})
sumAB
system.time(sumBA <- sum(a < b))
sumBA