I am not sure if this has been asked here, But I am very confused here. I am reading this awesome book called Advanced R by Hadley Wickham from here.
There is function called cement
that has been described here, I have modified it little bit and trying to understand it.
library(rlang)
cement1 <- function(x) {
dots <- expr(x)
print(class(dots))
#paste(expr_name(x))
}
cement2 <- function(y,z) {
dots <- exprs(y,z)
print(class(dots))
#paste(purrr::map(dots, expr_name), collapse = " ")
}
Running the above cement1
without any parameter returns me the class of dots as "name".
However, when I run the cement2
function with additional parameter, the class returns "list", {simply putting class(expr(x)) returns "name" whereas class(exprs(x)) returns "list"}.
I am not getting my head around this as why it is printing different class returned by expr
and exprs
. The only difference I thought I knew about them was, one deals with one parameter, other one deals with multiple parameters, but I may be wrong, I might have missed some details.
Original Problem: So, it all started by running these two functions separately by removing the comments section in the code for both cement1
and cement2
, when I run the functions Below are the output returned by them:
cement1(Hello) #Returns , Error in type_of(.x) : object 'Hello' not found
cement2(Hello) #Works very well and returns, [1] "y z"
So I tried to find the reason why cement1
failed and then printed their classes and that is when I realized , expr
and exprs
return different classes.
My question is:
1) Are they by design, if yes then why? Or, I am doing some horrible mistake, which I am currently unable to see.
2) Does cement1
can't work this if not , what is the correct way?
I am sorry for too long sentences, My first language is not English, hence If anything silly is there, Please let me know I shall correct it. I hope this is not a duplicate, I tried to find the answer but could not found by my own.
Thanks for any help.
R Version: 3.4.2 rlang: 0.2.0
1) Yes, the return values of
expr
andexprs
differ by design. From the?expr
help page:2)
expr_name()
expects a quoted expression, such as what's produced byexpr()
. So, you need to modify yourcement1
to callexpr_name()
ondots
, notx
. You can also removepaste
because you are not concatenating anything.Your function
cement2
basically callsexpr_name()
on every element of the list returned byexprs()
, then concatenates the results into a single string.2a) Now that we got your
cement1
working, we can improve it further. Currently, the function doesn't make any use of its input argumentx
.expr()
simply captures the unevaluated expression, and this expression will always bex
, regardless of what you name your argument:However, if you replace
expr()
withenexpr()
, the function will substitute the expression provided as the function's argument and capture that instead: