我不知道是否在这里被问到了,但是我在这里很困惑。我正在阅读here中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
函数时,该类返回“列表”,{简单地将class(expr(x))返回“名称”,而class(exprs(x))返回“列表”}。我并没有解决这个问题,因为它为什么要打印
expr
和exprs
返回的不同类。我以为我了解它们的唯一区别是,一个处理一个参数,另一个处理多个参数,但是我可能错了,我可能错过了一些细节。原始问题:因此,当我运行函数时,都通过删除
cement1
和cement2
的代码中的注释部分来分别运行这两个函数,这都是它们返回的输出:cement1(Hello) #Returns , Error in type_of(.x) : object 'Hello' not found
cement2(Hello) #Works very well and returns, [1] "y z"
因此,我试图找出
cement1
失败的原因,然后打印其类,也就是当我意识到expr
和exprs
返回不同的类时。我的问题是:
1)它们是设计使然吗?或者,我正在犯一些可怕的错误,目前无法看到。
2)如果
cement1
不能正常工作,正确的方法是什么?很抱歉,句子太长,我的母语不是英语,因此,如果有任何愚蠢之处,请告诉我,我将纠正它。我希望这不是重复的,我试图找到答案,但我自己找不到。
谢谢你的帮助。
R版本:3.4.2
朗朗:0.2.0
最佳答案
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
工作了,我们可以进一步改进它。当前,该函数未使用其输入参数x
。 expr()
只是捕获未计算的表达式,而无论您用什么名字命名,此表达式始终为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"