4

我不确定这里是否有人问过这个问题,但我在这里很困惑。我正在从这里阅读 Hadley Wickham 的这本很棒的书,名为 Advanced R。

这里已经描述了一个被调用的函数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代码会将点类返回为“名称”。

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

我不明白为什么它打印由exprand返回的不同类exprs。我以为我知道它们的唯一区别是,一个处理一个参数,另一个处理多个参数,但我可能错了,我可能错过了一些细节。

原始问题:所以,这一切都是从分别运行这两个函数开始的,方法是删除代码中的注释部分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

4

1 回答 1

1

1) 是的, 和 的返回值因设计expr而异。exprs?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"
于 2018-08-23T02:48:09.897 回答