R&quosures-如何获取作为函数参数传递的向量中包含的符号的名称?

时间:2018-08-31 11:11:12

标签: r quosure

我想编写一个R函数arg2str,该函数返回作为参数输入的符号的名称(字符串的向量)。

在最简单的情况下,我只有一个输入符号:

library ("rlang")

arg2str.v0 <- function (arg) rlang::quo_name (enquo (arg))
arg2str.v0 (a)
## [1] "a"

如果我有多个符号,则可以使用三点结构:

arg2str.v1 <- function (...) sapply (enquos (...), rlang::quo_name)
arg2str.v1 (a, b, c)
##             
## "a" "b" "c"

(辅助问题:为什么在这种情况下,显示的字符串矢量带有初步的换行符而不是初步的[1]?)

但是我实际上想处理符号向量。但是:

sym2str.v1 (c(a, b, c))
##
## "c(a, b, c)"

如何调整我的功能呢?


我的第一个直觉是首先通过使用sapply来对参数向量中包含的符号进行报价(而不是对参数向量本身进行报价),然后将rlang::quo_name应用于所得的结果向量。但是,似乎在sapply上对其进行调用之前,在enquote内对自变量向量中的符号进行了评估:

arg2str.v2 <- function (args) {
    enquo_args <- sapply (args, enquo)
    lapply (enquo_args, rlang::quo_name)
}
arg2str.v2 (c (a, b, c))
## Error in lapply(X = X, FUN = FUN, ...) : object 'a' not found

3 个答案:

答案 0 :(得分:1)

使用substitutedeparse的一个可能的骇客答案:

arg2str.v3 <- function (args) {
    strs <- sapply (substitute (args), deparse)
    if (length (strs) > 1) { strs <- strs [-1] }
    return (strs)
}
arg2str.v3 (c (a, b, c))
## [1] "a" "b" "c"

请注意,如果提供命名矢量作为输入,它也会保留名称:

arg2str.v3 (c (n1 = a, n2 = b, n3 = c))
##  n1  n2  n3 
## "a" "b" "c"

答案 1 :(得分:0)

我不确定您想要的内容是否有矢量化的tidyeval操作。您可以尝试

f <- function(v) {
    v <- rlang::quo_name(enquo(v))
    gsub('^c\\(|\\s|\\)$', '', v) %>% 
        strsplit(',') %>% 
        unlist 
}

f(c(a, b, c))
#[1] "a" "b" "c"

可以与ac(a)c(a, b)形式的输入一起使用,但是有点hacky ...

您的副问题的答案(为什么arg2str.v1(a, b, c)不在行首打印"[1]")是它返回了一个命名向量,其名称为空字符串(例如,与set_names(c('a', 'b', 'c'), c('', '', ''))的输出)。

答案 2 :(得分:0)

使用rlang约定,这应该可以工作:

return_args <- function(args){

    args_expr <- enexpr(args)

    if(length(args_expr) == 1) {
        args_vars <- as.list(args_expr)
    } else {
        args_vars <- as.list(args_expr)[-1]
    }

    sapply(args_vars, quo_name)
}


return_args(c(a, b, c))
[1] "a" "b" "c"

return_args(a)
[1] "a"