MIS 207

Introduction to R Language
Control Structures and Functions


I. Ozkan, PhD

Professor
MIS
Cankaya University

iozkan@cankaya.edu.tr

Fall 2025

Reference

Quick Refresher from Previous Classes

✅ Tidyverse style guide

✅ Frequently used [some] functions

✅ Data Types in

✅ Data Creation in

❌ Control Structures in

❌ Functions in

Control Structures

Control-Flow Constructs: if construct

if( condition ) {

expression/do something

}

# Basic If construct  

if (5>3) print("Five is greater than three")  
## [1] "Five is greater than three"
if (TRUE) print("Condition is TRUE")  
## [1] "Condition is TRUE"
if (3>5) print("3>5")  # nothing happens

Control-Flow Constructs: if construct

if( condition ) {

expression/do something

}

# number as a condition?
if (1) print("Condition is TRUE")  
## [1] "Condition is TRUE"
if (0) print("Condition is TRUE")  
if (-1) print("Condition is TRUE")  
## [1] "Condition is TRUE"
if (11) print("Condition is TRUE")  
## [1] "Condition is TRUE"
if (0.1) print("Condition is TRUE")  
## [1] "Condition is TRUE"
if (-0.1) print("Condition is TRUE")  
## [1] "Condition is TRUE"
# if(c(0,3)) print("Condition is TRUE") 
# throws error condition length > 1 

Control-Flow Constructs: if construct

if( condition ) {

expression/do something

}

# using variables  
x <- 5  
y <- 3 

if(x>y) print("x is greater than y")  
## [1] "x is greater than y"
x <- 3:12 # vector
y <- 1:10 # vector 

# Recall: condition must have a length of one 
# if(x>y) print("x is greater than y")  
# Error in if (x > y) print("x is greater than y") : 
#  the condition has length > 1

x>y
##  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
if (sum(x>y)>0) print("x has elements that are greater than elements of y")  
## [1] "x has elements that are greater than elements of y"
if(sum(x>y)>0 & sum(x>y)==length(x)) { 

  print("Element-wise all elements of x are greater than elements of y")  
  
}
## [1] "Element-wise all elements of x are greater than elements of y"
if (sum(x>y)) { 

  print(paste0("Element-wise x has ", sum(x>y), " elements that are greater than elements of y")) 
  
}
## [1] "Element-wise x has 10 elements that are greater than elements of y"

Control-Flow Constructs: if-and-else construct

if( condition ) {

do something

}
else {

do something different

}

set.seed(123)
x <- sample(-10:10, 6) # 6 random numbers
y <- sample(-10:10, 6) # 6 random numbers

x>y
## [1]  TRUE  TRUE FALSE FALSE  TRUE FALSE
if(sum(x>y)>0) print("x has elements that are greater than elements of y") else print("x has no element that is greater than elements of y")
## [1] "x has elements that are greater than elements of y"
if (sum(x>y)) {
  
  print(paste0("x has ", sum(x>y), " elements that are greater than elements of y")) 

} else { 
    
  print("x has no element that is greater than elements of y")
  
} 
## [1] "x has 3 elements that are greater than elements of y"

Control-Flow Constructs: ifelse

ifelse(condition,expression if TRUE,expression if FALSE)

s <- ifelse (5 > 3, "Five is greater than three", "Five is not greater than three")  
s
## [1] "Five is greater than three"
x <- c(6:-4)
sqrt(x) # not a number NaN
##  [1] 2.449490 2.236068 2.000000 1.732051 1.414214 1.000000 0.000000      NaN
##  [9]      NaN      NaN      NaN
sqrt(ifelse (x >= 0, x, NA)) # vectorized conditions
##  [1] 2.449490 2.236068 2.000000 1.732051 1.414214 1.000000 0.000000       NA
##  [9]       NA       NA       NA
# vectorized conditions 

x <- 1:10
x
##  [1]  1  2  3  4  5  6  7  8  9 10
ifelse(x %% 5 == 0, "XXX", as.character(x))
##  [1] "1"   "2"   "3"   "4"   "XXX" "6"   "7"   "8"   "9"   "XXX"
ifelse(x %% 2 == 0, "even", "odd")
##  [1] "odd"  "even" "odd"  "even" "odd"  "even" "odd"  "even" "odd"  "even"

Control-Flow Constructs: ifelse

ifelse(condition,expression if TRUE,expression if FALSE)

data(iris)

# create a new column containing "Large" and "Small"
iris$new.colum <- iris$Sepal.Length * iris$Sepal.Width
head(iris,3)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species new.colum
## 1          5.1         3.5          1.4         0.2  setosa     17.85
## 2          4.9         3.0          1.4         0.2  setosa     14.70
## 3          4.7         3.2          1.3         0.2  setosa     15.04
iris$new.colum <- ifelse (iris$new.colum > median(iris$new.colum), "Large", "Small")
head(iris,3)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species new.colum
## 1          5.1         3.5          1.4         0.2  setosa     Large
## 2          4.9         3.0          1.4         0.2  setosa     Small
## 3          4.7         3.2          1.3         0.2  setosa     Small

Control-Flow Constructs: if-and-else if-and-else construct

if( condition ) {

do something

}
else if( condition2 ) {

do something different

}
else if( condition3 ) {

do something different

}
else {

do something different

}

result <- 65

if (result > 90) {
  "A"
} else if (result > 80) {
    "B"
} else if (result > 50) {
    "C"
} else {
  "F"
}
## [1] "C"

Control-Flow Constructs: Switch

switch(expression,list of values)

x <- "c"

if (x == "a") {
  "option 1"
} else if (x == "b") {
  "option 2" 
} else if (x == "c") {
  "option 3"
} else {
  stop("Invalid `x` value")
}
## [1] "option 3"
# or switch 

switch(x,
  a = "option 1",
  b = "option 2",
  c = "option 3",
  stop("Invalid `x` value")
)
## [1] "option 3"

Control-Flow Constructs: Switch

(switch("c", a = 1, b = 2))
## NULL
x <- "horse"
switch(x,
    cow = ,
    horse = ,
    dog = 4,
    human = ,
    chicken = 2,
    plant = 0,
    stop("Unknown input")
)
## [1] 4

Control-Flow Constructs: Switch

# corresponding item in the list is returned
switch(2,"aa","bb","cc")  
## [1] "bb"
switch(3,"aa","bb","cc")  
## [1] "cc"
# example from https://www.geeksforgeeks.org/switch-case-in-r/
val1 = 6
val2 = 7
val3 = "s"
switch(
    val3,
    "a"= cat("Addition =", val1 + val2),
    "d"= cat("Subtraction =", val1 - val2),
    "r"= cat("Division = ", val1 / val2),
    "s"= cat("Multiplication =", val1 * val2),
    "m"= cat("Modulus =", val1 %% val2),
    "p"= cat("Power =", val1 ^ val2),
        stop("Unknown input")
)
## Multiplication = 42
# or 
switch(
    val3,
    "a"= cat("Addition =", val1 + val2),
    "d"= cat("Subtraction =", val1 - val2),
    "r"= cat("Division = ", val1 / val2),
    "s"= cat("Multiplication =", a <- val1 * val2),
    "m"= cat("Modulus =", val1 %% val2),
    "p"= cat("Power =", val1 ^ val2),
        stop("Unknown input")
)
## Multiplication = 42
a
## [1] 42

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

# see ?cat function first: Concatenate and Print  
for(i in 1:5) cat(i)
## 12345
for(i in 1:5) cat("This is iteration i =", i,"\n") # special char: "\n"
## This is iteration i = 1 
## This is iteration i = 2 
## This is iteration i = 3 
## This is iteration i = 4 
## This is iteration i = 5

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

for(i in 1:5) i
for(i in 1:5) print(i)
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
for(i in 1:5) print(1:i)
## [1] 1
## [1] 1 2
## [1] 1 2 3
## [1] 1 2 3 4
## [1] 1 2 3 4 5

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

# for and switch
for(i in c(-1:3, 9))  print(switch(i, 7, 9 , 11, 5))
## NULL
## NULL
## [1] 7
## [1] 9
## [1] 11
## NULL
for(n in c(2,5,10,20,50)) {
  cat(n, ": ", n^2, " ",n^3, "\n", sep = "")
}
## 2: 4 8
## 5: 25 125
## 10: 100 1000
## 20: 400 8000
## 50: 2500 125000

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

letters  # letters 
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
length(letters)
## [1] 26
# modulo operator, see ?`%%`
for (i in 1:length(letters)){
  if((i %% 4)==0) cat(i,": ",letters[i], "\n", sep = "")
}
## 4: d
## 8: h
## 12: l
## 16: p
## 20: t
## 24: x

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

nms <- c("Ayse", "Huseyin", "Serdar", "Hatice", "Safinaz") 

for(i in nms) {   
  print(paste("The name", i, "has", nchar(i), "characters"))
}
## [1] "The name Ayse has 4 characters"
## [1] "The name Huseyin has 7 characters"
## [1] "The name Serdar has 6 characters"
## [1] "The name Hatice has 6 characters"
## [1] "The name Safinaz has 7 characters"

Control-Flow Constructs: for loop (teaser-stringr & regex)

for(item in vector) {
perform_action
}

# a bit complex one, extract all unique characters from string using
# stringr package function, see ?str_match_all, and regex 
library(stringr)
for(i in nms) {   
  print(paste(i, "has", nchar(i), "characters","and",length(unique(str_match_all(i, "(?<=(\\w{1}))")[[1]][,2])),"unique characters:",paste(unique(str_match_all(i, "(?<=(\\w{1}))")[[1]][,2]),collapse=", ")))
}
## [1] "Ayse has 4 characters and 4 unique characters: A, y, s, e"
## [1] "Huseyin has 7 characters and 7 unique characters: H, u, s, e, y, i, n"
## [1] "Serdar has 6 characters and 5 unique characters: S, e, r, d, a"
## [1] "Hatice has 6 characters and 6 unique characters: H, a, t, i, c, e"
## [1] "Safinaz has 7 characters and 6 unique characters: S, a, f, i, n, z"

Control-Flow Constructs:

for(item in vector) {
perform_action
}

# results in vectors 
x <- c()
for (i in 1:7){
  x <- rbind(x, c(i,i^2)) # rbind: combine R objects by rows 
}
x # 2 dimensional 
##      [,1] [,2]
## [1,]    1    1
## [2,]    2    4
## [3,]    3    9
## [4,]    4   16
## [5,]    5   25
## [6,]    6   36
## [7,]    7   49

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

# nested loop 
for(i in 1:2) { # first loop, 
  for(j in 1:3) { # second loop inside
    cat("This is iteration i =", i, "and j =", j,"\n") 
  } # end of second loop
} # end of first loop
## This is iteration i = 1 and j = 1 
## This is iteration i = 1 and j = 2 
## This is iteration i = 1 and j = 3 
## This is iteration i = 2 and j = 1 
## This is iteration i = 2 and j = 2 
## This is iteration i = 2 and j = 3
x <- c()
for(i in 1:5) { # first loop, 
  for(j in 1:3) { # second loop inside
    x <- c(x, paste(LETTERS[i], j, sep = "_"))  # Code block
  } # end of second loop
} # end of first loop
x
##  [1] "A_1" "A_2" "A_3" "B_1" "B_2" "B_3" "C_1" "C_2" "C_3" "D_1" "D_2" "D_3"
## [13] "E_1" "E_2" "E_3"

Control-Flow Constructs: for loop

for(item in vector) {
perform_action
}

# break a loop if i > 4 break  
for (i in 1:10){
  if(i<5) cat(i,": ",i^2, "\n", sep = "") else {
    cat(i,": ", "break \n", sep = "")
    break
  }
}
## 1: 1
## 2: 4
## 3: 9
## 4: 16
## 5: break
# conditional skip  
for(i in 1:10) {
  if(i %in% c(1, 5, 7)) { # do not execute for these numbers 
    next
  }
  cat(i,": ",i^2, "\n", sep = "")  
}
## 2: 4
## 3: 9
## 4: 16
## 6: 36
## 8: 64
## 9: 81
## 10: 100

Control-Flow Constructs: while loop

while(condition){
perform_action
}

x <- 5

while(x < 10) {
  x <- x + 1    
  cat("x: ", x, "   1:x->", 1:x, "\n") 
}
## x:  6    1:x-> 1 2 3 4 5 6 
## x:  7    1:x-> 1 2 3 4 5 6 7 
## x:  8    1:x-> 1 2 3 4 5 6 7 8 
## x:  9    1:x-> 1 2 3 4 5 6 7 8 9 
## x:  10    1:x-> 1 2 3 4 5 6 7 8 9 10

Control-Flow Constructs: while loop

while(condition){
perform_action
}

# while with break
x <- 5
while(TRUE) {
  cat("x: ", x, "\n") 
  x <- x+1
  if(x%%4==0) break
}
## x:  5 
## x:  6 
## x:  7

Control-Flow Constructs: while loop

while(condition){
perform_action
}

# nested loop for in while
i <- 2
while(i <= 3) {
  for(j in 1:4) {
    print(paste("This is iteration i =", i, "and j =", j))
  }
  i <- i + 1
}
## [1] "This is iteration i = 2 and j = 1"
## [1] "This is iteration i = 2 and j = 2"
## [1] "This is iteration i = 2 and j = 3"
## [1] "This is iteration i = 2 and j = 4"
## [1] "This is iteration i = 3 and j = 1"
## [1] "This is iteration i = 3 and j = 2"
## [1] "This is iteration i = 3 and j = 3"
## [1] "This is iteration i = 3 and j = 4"
# nested loop while in while
i <- 2
while(i <= 3) {
  j <- 1
  while(j <= 3) {
    print(paste("This is iteration i =", i, "and j =", j))
    j <- j + 1
  }
  i <- i + 1
}
## [1] "This is iteration i = 2 and j = 1"
## [1] "This is iteration i = 2 and j = 2"
## [1] "This is iteration i = 2 and j = 3"
## [1] "This is iteration i = 3 and j = 1"
## [1] "This is iteration i = 3 and j = 2"
## [1] "This is iteration i = 3 and j = 3"

Control-Flow Constructs: while loop

while(condition){
perform_action
}

nms <- c("Ayse", "Huseyin", "Serdar", "Hatice", "Safinaz") 

i <- 1
while(i<=length(nms)) {   
  print(paste("The name", nms[i], "has", nchar(nms[i]), "characters"))
  i <- i + 1
}
## [1] "The name Ayse has 4 characters"
## [1] "The name Huseyin has 7 characters"
## [1] "The name Serdar has 6 characters"
## [1] "The name Hatice has 6 characters"
## [1] "The name Safinaz has 7 characters"

Control-Flow Constructs: while loop

while(condition){
perform_action
}

nms <- c("Ayse", "Huseyin", "Serdar", "Hatice", "Safinaz") 

# a bit complex one, extract all characters from string using
# stringr package function, see ?str_match_all, and regex 
i <- 1
while(i<=length(nms)) {   
  print(paste(nms[i], "has", nchar(nms[i]), "characters","and",length(unique(str_match_all(nms[i], "(?<=(\\w{1}))")[[1]][,2])),"unique characters:",paste(unique(str_match_all(nms[i], "(?<=(\\w{1}))")[[1]][,2]),collapse=", ")))
    i <- i + 1
}
## [1] "Ayse has 4 characters and 4 unique characters: A, y, s, e"
## [1] "Huseyin has 7 characters and 7 unique characters: H, u, s, e, y, i, n"
## [1] "Serdar has 6 characters and 5 unique characters: S, e, r, d, a"
## [1] "Hatice has 6 characters and 6 unique characters: H, a, t, i, c, e"
## [1] "Safinaz has 7 characters and 6 unique characters: S, a, f, i, n, z"

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

x <- 4
x
## [1] 4
repeat{
  cat("x: ", x, "   1:x->", 1:x, "\n") 
  x <- x + 1    
  if(x == 8) break
}
## x:  4    1:x-> 1 2 3 4 
## x:  5    1:x-> 1 2 3 4 5 
## x:  6    1:x-> 1 2 3 4 5 6 
## x:  7    1:x-> 1 2 3 4 5 6 7

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

x <- 6
x
## [1] 6
repeat{
  cat("x: ", x, "\n") 
  x <- x + 1
  if(x%%5==0) break
}
## x:  6 
## x:  7 
## x:  8 
## x:  9

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

# nested loop for in repeat
i <- 2
repeat{
  for(j in 1:3) {
    print(paste("This is iteration i =", i, "and j =", j))
  }
  i <- i + 1
  if(i > 3) break 
}
## [1] "This is iteration i = 2 and j = 1"
## [1] "This is iteration i = 2 and j = 2"
## [1] "This is iteration i = 2 and j = 3"
## [1] "This is iteration i = 3 and j = 1"
## [1] "This is iteration i = 3 and j = 2"
## [1] "This is iteration i = 3 and j = 3"

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

# nested loop repeat in while
i <- 2
while(i <= 3) {
  j <- 1
  repeat{
    print(paste("This is iteration i =", i, "and j =", j))
    j <- j + 1
    if(j > 5) break
  }
  i <- i + 1
}
## [1] "This is iteration i = 2 and j = 1"
## [1] "This is iteration i = 2 and j = 2"
## [1] "This is iteration i = 2 and j = 3"
## [1] "This is iteration i = 2 and j = 4"
## [1] "This is iteration i = 2 and j = 5"
## [1] "This is iteration i = 3 and j = 1"
## [1] "This is iteration i = 3 and j = 2"
## [1] "This is iteration i = 3 and j = 3"
## [1] "This is iteration i = 3 and j = 4"
## [1] "This is iteration i = 3 and j = 5"

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

# nested loop repeat in repeat
i <- 2
repeat{
  j <- 1
  repeat{
    print(paste("This is iteration i =", i, "and j =", j))
    j <- j + 1
    if(j > 5) break
  }
  i <- i + 1
  if(i > 3) break 
}
## [1] "This is iteration i = 2 and j = 1"
## [1] "This is iteration i = 2 and j = 2"
## [1] "This is iteration i = 2 and j = 3"
## [1] "This is iteration i = 2 and j = 4"
## [1] "This is iteration i = 2 and j = 5"
## [1] "This is iteration i = 3 and j = 1"
## [1] "This is iteration i = 3 and j = 2"
## [1] "This is iteration i = 3 and j = 3"
## [1] "This is iteration i = 3 and j = 4"
## [1] "This is iteration i = 3 and j = 5"

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

nms <- c("Ayse", "Huseyin", "Serdar", "Hatice", "Safinaz") 

i <- 1
repeat{   
  print(paste("The name", nms[i], "has", nchar(nms[i]), "characters"))
  i <- i + 1
  if (i > length(nms)) break 
}
## [1] "The name Ayse has 4 characters"
## [1] "The name Huseyin has 7 characters"
## [1] "The name Serdar has 6 characters"
## [1] "The name Hatice has 6 characters"
## [1] "The name Safinaz has 7 characters"

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

nms <- c("Ayse", "Huseyin", "Serdar", "Hatice", "Safinaz") 

# a bit complex one, extract all characters from string using
# stringr package function, see ?str_match_all, and regex 
i <- 1
repeat{   
  print(paste(nms[i], "has", nchar(nms[i]), "characters","and",length(unique(str_match_all(nms[i], "(?<=(\\w{1}))")[[1]][,2])),"unique characters:",paste(unique(str_match_all(nms[i], "(?<=(\\w{1}))")[[1]][,2]),collapse=", ")))
  i <- i + 1
  if (i > length(nms)) break 
}
## [1] "Ayse has 4 characters and 4 unique characters: A, y, s, e"
## [1] "Huseyin has 7 characters and 7 unique characters: H, u, s, e, y, i, n"
## [1] "Serdar has 6 characters and 5 unique characters: S, e, r, d, a"
## [1] "Hatice has 6 characters and 6 unique characters: H, a, t, i, c, e"
## [1] "Safinaz has 7 characters and 6 unique characters: S, a, f, i, n, z"

Control-Flow Constructs: repeat loop

repeat{
perform_action
until break
}

Functions in R

Three Components of a Function in R

Example: formals(sd)

$x

$na.rm
[1] FALSE

Example: body(sd)

sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), 
    na.rm = na.rm))

Example: environment(sd)

<environment: namespace:stats>

Function: Basic Syntax

Name of Function

Consider proper name that is understandable

Arguments of Function

Data, values for some parameters are passed through the body code using arguments

Function returns

Either plot, data, values etc., are returned. return() function is frequently used.

function_name <- function(argument_1, argument_2, argument_3,...){
  
           function_task/Body
  
           return(output)
}

Function: Function Name

# Good
add_row()
permute()

# Bad
row_adder()
permutation()

Function: Function Name

long_function_name <- function(a = "a long argument",
                               b = "another argument",
                               c = "another long argument") {
  # As usual code is indented by two spaces.
}

or

long_function_name <- function(
    a = "a long argument",
    b = "another argument",
    c = "another long argument") {
  # As usual code is indented by two spaces.
}

Function: return

return() function should be used for early return. The last evaluated expression automatically returned otherwise

# Good
find_abs <- function(x) {
  if (x > 0) {
    return(x)
  }
  x * -1
}

add_two <- function(x, y) {
  x + y
}

# Bad
add_two <- function(x, y) {
  return(x + y)
}

find_abs <- function(x) {
  if (x > 0) return(x)
  x * -1
}

Function: A Very Basic Example

f <- function() { # function name = f, class = function
  
  # Empty Function No Task, return nothing: NULL
  
}

f()
## NULL
class(f) 
## [1] "function"
formals(f)
## NULL
# another one 
f <- function() {
  
  cat("Hello, world!\n")
  
}

Function: Argument(s)

# Argument without default 
f <- function(person) {
  
  cat("Hello ", person, "!\n")
  
}

# f()
# Error in f() : argument "person" is missing, with no default

f("Ali")
## Hello  Ali !
f(person = "Ali")
## Hello  Ali !
# Argument with default 
f <- function(person = "Ali") {
  
  cat("Hello ", person, "!\n")
  
}

Function: Argument Matching

# Argument with default 
f <- function(person = "Ali", age = 22) {
  
  cat("Hello ", person, ". You are", age, "years old \n")
  
}

f()
## Hello  Ali . You are 22 years old
f("Veli") # Positional matching of first argument
## Hello  Veli . You are 22 years old
f(person = "Veli") # by name matching of first argument
## Hello  Veli . You are 22 years old
f("Veli", 29) # Positional matching of both 
## Hello  Veli . You are 29 years old
f(person = "Veli", age = 29) # by name matching of both 
## Hello  Veli . You are 29 years old
f(per = "Veli", age = 29) # partial matching of person  
## Hello  Veli . You are 29 years old
f(age = 23, "Ece") # mix matching  
## Hello  Ece . You are 23 years old

Built-in Functions Help Pages

Check the function’s help page with ?mean

Let’s take 2 minutes to investigate the help page for mean in R Studio or Click to Read Online

mean(x = temp_high_forecast, trim = 0, na.rm = FALSE, ...)

Function: Example

# A function difficult to read  
sqr <- function(x) x*x 

sqr(10)
## [1] 100
sqr(1:5)
## [1]  1  4  9 16 25
# easier to read 
my_squre <- function(x=0) {
  x*x
}

my_squre()
## [1] 0
my_squre(10)
## [1] 100
my_squre(1:5)
## [1]  1  4  9 16 25

Function: Example

# using, other functions utils function tail() and base
# function, cumprod() 
my_factorial2 <- function(n=1) {
  if (n == 0) {
    return(1)
  } else {
    if(n < 0) {
      return(NaN)
    }
    tail(cumprod(1:n),1)
  }
}

my_factorial2(-2)
## [1] NaN
my_factorial2(0)
## [1] 1
my_factorial2(2)
## [1] 2
my_factorial2(5)
## [1] 120

Function: Recursive Function Example

# using, utils function tail() and base function, cumprod(): ? 
my_factorial2 <- function(n=1) {
  if (n == 0) {
    return(1)
  } else {
    if(n < 0) {
      return(NaN)
    }
    tail(cumprod(1:n),1)
  }
}

my_factorial2(-2)
## [1] NaN
my_factorial2(0)
## [1] 1
my_factorial2(2)
## [1] 2
my_factorial2(5)
## [1] 120

Function: Lazy Evaluation

f <- function(a, b) {
  a^2
} 
f(2)  
## [1] 4
# does not produce an error because the 2 gets
# positionally matched to argument a 

# f(b = 2)  
# Error in f(b = 2) : argument "a" is missing, with no default

Function: Lazy Evaluation

# using eval(), substitute() functions
# ?eval and ?substitute for help 
my_function <- function(my_expression, x) {
  eval(substitute(my_expression))
}

my_function(my_expression = x^2-1, x = 3)
## [1] 8
my_function(my_expression = x^2-3*x-1, x = 3)
## [1] -1
my_function(x^2-1,3) # positionally matched
## [1] 8
my_function(x^2-1,1:5) # x now is a vector 
## [1]  0  3  8 15 24

Function: Lazy Evaluation

# Plotting function using plot() and seq() function 
seq(from = 3, to = 5, length.out = 5)
## [1] 3.0 3.5 4.0 4.5 5.0
my_curve <- function(my_expression, from, to) {
  x <- seq(from=from, to=to, length.out=100)
  y <- eval(substitute(my_expression)) 
  plot(x,y, type = "l")
}

my_curve(x^2-1,from=-2, to=2)

Function: Lazy Evaluation

# Plotting function using plot() and seq() function 
my_curve <- function(my_expression, from, to) {
  x <- seq(from=from, to=to, length.out=100)
  y <- eval(substitute(my_expression)) 
  plot(x,y, type = "l")
}


my_curve(-2*x^2 + 3*x -1,from=-2, to=2)

# what if argument is missing   
# my_curve(-2*x^2 + 3*x -1, to=2)  
# Error in seq(from = from, to = to, length.out = 100) :
#  argument "from" is missing, with no default

Function: Practice

my_curve2 <- function(my_expression, from, to) {
  if (missing(from)){
    print("Arguemnt `from` is missing") 
    return(NULL)
  } 
  if (missing(to)){
    print("Arguemnt `to` is missing") 
    return(NULL)
  } 
  x <- seq(from=from, to=to, length.out=100)
  y <- eval(substitute(my_expression)) 
  plot(x,y, type = "l")
}

my_curve2(-2*x^2 + 3*x -1,from=-2, to=2) 

my_curve2(-2*x^2 + 3*x -1, to=2) 
## [1] "Arguemnt `from` is missing"
## NULL
my_curve2(-2*x^2 + 3*x -1, from=2)  
## [1] "Arguemnt `to` is missing"
## NULL

Function: Practice

# defaults: from = 2, to = 2
my_curve3 <- function(my_expression, from=-2, to=2) {
  x <- seq(from=from, to=to, length.out=100)
  y <- eval(substitute(my_expression)) 
  plot(x,y, type = "l")
}

par(mfrow = c(2,2)) # 4 plotting window, 2x2
my_curve3(-2*x^2 + 3*x -1) 

my_curve3(-2*x^2 + 3*x -1, to=4) 

my_curve3(-2*x^2 + 3*x -1, from=-4)

my_curve3(-2*x^2 + 3*x -1, from = -4, to = 4)

par(mfrow = c(1,1)) # 1 plotting window