3

我想编写一个 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)"

我如何调整我的功能来做到这一点?


我的第一个直觉是首先通过 using 引用参数向量中包含的符号sapply(而不是引用参数向量本身),然后应用于rlang::quo_name得到的 quosures 向量。但似乎参数向量中的符号在对它们中的每一个调用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
4

3 回答 3

3

使用 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"

于 2019-08-29T11:27:39.243 回答
1

我不确定是否有你想要的矢量化 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('', '', '')))。

于 2018-08-31T14:01:13.773 回答
1

substitute 使用and的一种可能的骇人听闻的答案deparse

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"
于 2018-08-31T16:52:44.697 回答