R中的rlang中expr和exprs的类不同!为什么呢?

时间:2018-05-25 12:23:32

标签: r rlang nse quasiquotes

我不确定这里是否有人问过,但我在这里很困惑。我正在阅读这本名为Advanced R的书,由Hadley Wickham撰写,来自here

此处描述了一个名为cement的函数,我对其进行了一些修改并试图理解它。

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 = " ")
}

在没有任何参数的情况下运行上面的cement1会将点类别返回为“name”。

但是,当我使用附加参数运行cement2函数时,该类返回“list”,{简单地将class(expr(x))返回“name”而class(exprs(x))返回“列表“}。

我没有理解为什么它会打印exprexprs返回的不同类。我认为我知道的唯一区别是,一个处理一个参数,另一个处理多个参数,但我可能错了,我可能错过了一些细节。

原始问题:所有这一切都是通过删除cement1cement2代码中的评论部分来单独运行这两个函数开始的,当我运行函数下面是它们返回的输出:

cement1(Hello) #Returns , Error in type_of(.x) : object 'Hello' not found 
cement2(Hello) #Works very well and returns, [1] "y z"

所以我试图找出cement1失败的原因然后打印他们的课程,那时我意识到,exprexprs会返回不同的课程。

我的问题是

1)它们是否按设计设计,如果是,那为什么?或者,我正在做一些可怕的错误,我目前无法看到。

2)如果没有,cement1不能正常工作,这是正确的方法吗?

我很抱歉句子太长,我的第一语言不是英语,所以如果有什么傻话,请告诉我,我会更正。我希望这不是重复,我试图找到答案,但我自己找不到。

感谢您的帮助。

R版:3.4.2 rlang :0.2.0

1 个答案:

答案 0 :(得分:1)

1)是,exprexprs的返回值在设计上有所不同。在?expr帮助页面上:

  

enexpr()和expr()捕获单个原始表达式。

     

enexprs()和exprs()捕获一系列原始表达式,包括...中包含的表达式。

2)expr_name()需要带引号的表达式,例如expr()产生的表达式。因此,您需要修改cement1才能在expr_name()而非dots上调用x。您也可以删除paste,因为您没有串联任何内容。

cement1 <- function(x) {
  dots <- expr(x)
  # print(class(dots))      ## Commented out for clarity
  expr_name(dots)           ## The input to expr_name is now effectively expr(x)
}
cement1( Hello )
# "x"

您的函数cement2基本上对expr_name()返回的列表的每个元素调用exprs(),然后将结果串联为单个字符串。

2a)现在我们使您的cement1工作正常了,我们可以进一步改进它。当前,该函数未使用其输入参数xexpr()只是捕获未计算的表达式,而无论您用什么名字命名,该表达式始终为x

cement1.1 <- function( completelyIgnoredName ) {
  dots <- expr(x)
  expr_name(dots)
}
cement1.1( Hello )
# "x"

但是,如果将expr()替换为enexpr(),则该函数将替换作为函数参数提供的表达式,并捕获那个

cement1.2 <- function(x) {
  dots <- enexpr(x)
  expr_name(dots)
}
cement1.2( Hello )
# "Hello"