Reputation: 7457
I'm digging my head into R's non-standard evaluation mechanisms. Halfway there, I'm still stuck from time to time. ;-)
I made a little calculator
that pretty-prints the calculation together with the result:
calculator <- function(e) cat(deparse(substitute(e)), "=", e)
This works fine:
calculator(1 + 2)
prints:
1 + 2 = 3
However, when calling the calculator
with:
a <- 1; b <- 2
calculator(a + b)
the output is:
a + b = 3
How can I tweak my calculator
in order it prints 1 + 2 = 3
also in the later case?
I tried:
calculator2 <- function(e) {
ex <- lapply(substitute(e), function(x) ifelse(is.numeric(x), eval(x), x))
cat(deparse(ex), "=", e)
}
calculator2(1 + 2)
# list(+, 1, 2) = 3
calculator2(a + b)
# list(+, a, b) = 3
This obviously doesn't work. After the lapply
call I have a list and cat
prints list(+, 1, 2)
to the console.
So I made another try:
calculator3 <- function(e) {
ex <- substitute(e)
for(i in 1:length(ex)) {
if(is.numeric(ex[[i]])) ex[[i]] <- eval(ex[[i]])
}
cat(deparse(ex), "=", e)
}
calculator3(1 + 2)
# 1 + 2 = 3
calculator3(a + b)
# a + b = 3
..which is the same as my first version..
Upvotes: 4
Views: 120
Reputation: 132576
This works for an expression with one operator. For more complex expressions (which are nested function calls), you'll need to use recursion instead of the simple loops.
a <- 1; b <- 2
calculator1 <- function(e) {
expr <- substitute(e)
evalexpr <- lapply(expr, eval) #evaluate each part of expression
numind <- vapply(evalexpr, is.numeric, FUN.VALUE = logical(1))
expr[numind] <- evalexpr[numind]
cat(deparse(expr), "=", e)
}
calculator1(a + b)
#1 + 2 = 3
calculator1(1 + 2)
#1 + 2 = 3
Upvotes: 6