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
exprandexprsdiffer by design. From the?exprhelp page:2)
expr_name()expects a quoted expression, such as what's produced byexpr(). So, you need to modify yourcement1to callexpr_name()ondots, notx. You can also removepastebecause you are not concatenating anything.Your function
cement2basically callsexpr_name()on every element of the list returned byexprs(), then concatenates the results into a single string.2a) Now that we got your
cement1working, 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: