在 R 中:如何将函数名(不是字符)作为参数传递给另一个内部函数而不丢失初始函数名?

In R: how to pass function name (not as character) as an argument to another inner function without loss of initial function name?

我有两个功能:

  1. Worker that does the job
  2. Boss that calls the "Worker" and ask it to execute given function called by name

如果我直接调用 Worker,它会收到函数体及其名称,因此它可以同时使用两者。但是,如果我通过 Boss 调用 WorkerBoss 会将 Worker 中的函数名称屏蔽为 FUN

require(magrittr)    
require(dplyr)

df <- data.frame(one = c(1,1,1), two = c(1,3,NA))

Worker <- function(df, feature, FUN, ...) {
  newvarname <- paste0(substitute(FUN), feature)
  df %>% mutate(!!newvarname := FUN(!!as.name(feature), ...))
}

Boss <- function(df, feature, FUN, ...) {
  df %>% Worker(feature, FUN, ...)
}

Boss(df, "two", mean, na.rm = T)
   #   one two FUNtwo
   # 1   1   1      2
   # 2   1   3      2
   # 3   1  NA      2
Worker(df, "one", mean)
   #   one two meanone
   # 1   1   1       1
   # 2   1   3       1
   # 3   1  NA       1

我玩 quote/quo/enquo/substitute/get/match.fun 很累,但没有任何帮助。这是否意味着 R 不能将整个函数对象(名称和主体)作为参数传递?

可以在Boss里面加上eval(substitute()),不过好像不太满意

Boss <- function(df, feature, FUN, ...) {
  eval(substitute(df %>% Worker(feature, FUN,...)))
}

Boss(df, "two", mean, na.rm = T)
  one two meantwo
1   1   1       2
2   1   3       2
3   1  NA       2

这是一种处理方法 rlang:

library(rlang)

df <- data.frame(one = c(1,1,1), two = c(1,3,NA))

Worker <- function(df, feature, FUN, ...) {

    if (!is_quosure(FUN)) {
        fun_q <- quo(FUN)
        newvarname <- paste0(substitute(FUN), feature)
    }
    else {
        fun_q <- FUN
        newvarname <- paste0(quo_text(fun_q), feature)
    }

    df %>% mutate(!!newvarname := eval(fun_q)(!!as.name(feature), ...))
}

Boss <- function(df, feature, FUN, ...) {
    fun_q <- enquo(FUN)
    df %>% Worker(feature, fun_q, ...)
}

Boss(df, "two", mean, na.rm = T)

  one two meantwo
1   1   1       2
2   1   3       2
3   1  NA       2

Worker(df, "one", mean)

  one two meanone
1   1   1       1
2   1   3       1
3   1  NA       1