I'm a bit surprised by R's behaviour in a very specific case. Let's say I define a function square
that returns the square of its argument, like this:
square <- function(x) { return(x^2) }
I want to call this function within another function, and I also want to display its name when I do that. I can do that using deparse(substitute())
. However, consider the following examples:
ds1 <- function(x) {
print(deparse(substitute(x)))
}
ds1(square)
# [1] "square"
This is the expected output, so all is fine. However, if I pass the function wrapped in a list and process it using a for loop, the following happens:
ds2 <- function(x) {
for (y in x) {
print(deparse(substitute(y)))
}
}
ds2(c(square))
# [1] "function (x) " "{" " return(x^2)" "}"
Can anybody explain to me why this occurs and how I could prevent it from happening?
substitute() is often paired with deparse() . That function takes the result of substitute() , an expression, and turns it into a character vector.
deparse() function in R Language is used to convert an object of expression class to an object of character class.
As soon as you use x
inside your function, it is evaluated, so it "stops being an (unevaluated) expression" and "starts being its resulting values (evaluated expression)". To prevent this, you must capture x
by substitute
before you use it for the first time.
The result of substitute
is an object which you can query as if it was a list. So you can use
x <- substitute(x)
and then x[[1]]
(the function name) and x[[2]]
and following (the arguments of the function)
So this works:
ds2 <- function(x) {
x <- substitute(x)
# you can do `x[[1]]` but you can't use the expression object x in a
# for loop. So you have to turn it into a list first
for (y in as.list(x)[-1]) {
print(deparse(y))
}
}
ds2(c(square,sum))
## [1] "square"
## [1] "sum"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With