Expressions

“Encapsulated operations that can be executed in R”

An R expression vector is a list of calls, symbols etc.

Code -> quote() -> call

Create a call from code -> quote() Execute the call -> eval()

Call: an unevaluated function call, that is, an unevaluated expression

call_2_plus_2 <- quote(2 + 2)
eval(call_2_plus_2)
## [1] 4
class(call_2_plus_2)
## [1] "call"
str(call_2_plus_2)
##  language 2 + 2
call_2_plus_2
## 2 + 2

String -> parse() -> expression -> deparse() -> string

Transform a string into an expression -> parse() Execute the expression -> eval() (also)

str_2_plus_2 <- "2 + 2"
expr_2_plus_2 <- parse(text = str_2_plus_2)
eval(expr_2_plus_2)
## [1] 4
class(expr_2_plus_2)
## [1] "expression"
str(expr_2_plus_2)
##   expression(2 + 2)
expr_2_plus_2
## expression(2 + 2)

Transform a call into a string -> deparse()

deparse(call_2_plus_2)
## [1] "2 + 2"

Accessing and modifying calls and expressions content

# Let's build a call object from code
sum_call <- quote(sum(1, 5))
eval(sum_call)
## [1] 6

We can access the call content like a list:

sum_call[[1]]
## sum
sum_call[[2]]
## [1] 1
sum_call[[3]]
## [1] 5

And modify it:

sum_call[[1]] <- quote(paste0)
sum_call[[2]] <- quote(4)
sum_call[[3]] <- quote(6)
eval(sum_call)
## [1] "46"

Now with a expression:

str_2_plus_2 <- "2 + 2"
expr_2_plus_2 <- parse(text = str_2_plus_2)
expr_2_plus_2
## expression(2 + 2)
expr_2_plus_2[[1]]
## 2 + 2
expr_2_plus_2[[1]][1]
## `+`()
expr_2_plus_2[[1]][2]
## 2()
expr_2_plus_2[[1]][3]
## 2()

Composing calls with call()

sum_40_50_expr <- call("sum", 40, 50)
sum_40_50_expr
## sum(40, 50)
eval(sum_40_50_expr)
## [1] 90

Capturing calls with match.call()

return_expression <- function(...){
  match.call()
  }

return_expression(2, col = "blue", FALSE)
## return_expression(2, col = "blue", FALSE)

Manipulating calls

first_arg <- function(...){
  expr <- match.call()
  
  first_arg_expr <- expr[[2]]
  first_arg <- eval(first_arg_expr)
  
  if(is.numeric(first_arg))
  {
    paste("The first argument is", first_arg)
  } 
  else 
  {
    "The first argument is not numeric."
  }
}
first_arg(2, 4, "seven", FALSE)
## [1] "The first argument is 2"
first_arg("two", 4, "seven", FALSE)
## [1] "The first argument is not numeric."