【问题标题】:Getting name of a function passed as an argument to a function获取作为参数传递给函数的函数名称
【发布时间】:2019-04-02 10:45:10
【问题描述】:

背景

函数作为参数传递给函数。问题涉及:

  • 将该函数的名称作为字符串获取,以方便后续操作
  • 在调用该函数的包中定位该函数
  • 了解 ::::: 通话

示例

函数fun_tst在x上执行函数FUN

fun_tst <- function(x = 1:100, FUN = mean) {
    return(FUN(x))
}

mean

fun_tst()
# [1] 50.5

sum

fun_tst(x = 1:1e3, FUN = sum)
# [1] 500500

问题

fun_tst <- function(x = 1:100, FUN = mean) {
    msg <- paste("Executing function", FUN)
    print(msg)
    return(FUN(x))
} 


fun_tst(x = 1:1e3, FUN = sum)

粘贴错误(“执行函数”,FUN):无法强制类型 '内置'到'字符'类型的向量


尝试

1)

有趣的是,print 可以处理 FUN 对象但结果返回函数体。

fun_tst <- function(x = 1:100, FUN = mean) {
    print(FUN)
    return(FUN(x))
} 


fun_tst(x = 1:1e3, FUN = sum)

function (..., na.rm = FALSE) .Primitive("sum") [1] 500500

2) subsitute

fun_tst <- function(x = 1:100, FUN = mean) {
    fun_name <- substitute(FUN)
    msg <- paste("Executing function", fun_name, collapse = " ")
    print(msg)
    return(FUN(x))
} 


fun_tst(x = 1:1e3, FUN = sum)

>> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum"
[1] 500500

差不多了,但与 :: 一起使用时看起来一团糟,如下所示:

>> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function :: Executing function dplyr Executing function glimpse"
 int [1:1000] 1 2 3 4 5 6 7 8 9 10 ..

期望的结果

fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
# Executing function glimpse from package dplyr
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...

fun_tst(x = 1:1e3, FUN = sum)
# Executing function sum from package base

【问题讨论】:

  • 另一种选择是将函数名称作为字符传入,打印名称,然后使用evalparse调用函数。
  • @Frank 谢谢,听起来是个明智的建议。我希望也许有一种简单的方法可以“捞出”函数命名空间(包),它的名称无需解析,然后再次解析....

标签: r function functional-programming namespaces substitution


【解决方案1】:

第二次尝试(使用substitute)就快完成了。问题来自 R 将language 对象转换为字符的方式:

> as.character(substitute(dplyr::glimpse))
[1] "::"      "dplyr"   "glimpse" 

鉴于此,paste 以这种方式破坏它也就不足为奇了。我会通过分别处理这两种情况来解决这个问题:

fun_tst <- function(x = 1:100, FUN = mean) {
  fun_name <- substitute(FUN)
  if (length(fun_name) == 1) {
    msg <- paste("Executing function", fun_name, "from package base")
  } else {
    msg <- paste("Executing function", fun_name[3], "from package", fun_name[2])
  }
  print(msg)
  return(FUN(x))
} 

这适用于您的两个示例:

> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum from package base"
[1] 500500
> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function glimpse from package dplyr"
 int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...

但是,正如所写,它会认为全局环境中的所有函数都来自base,即使它们是用户定义的或通过library 调用引入的。如果这是您的用例,请不要明确地说“来自包库”。

【讨论】:

    【解决方案2】:

    如果您使用deparse()substitute,您将获得所需的输出,请参阅有关将变量名称传递给plot()https://*.com/a/9666650/1993932 的类似帖子。

    fun_tst <- function(x = 1:100, FUN = mean) {
      message(paste("Executing function",deparse(substitute(FUN))))
      return((FUN(x)))
    }
    > fun_tst(x = 1:1e3, FUN = sum)
    Executing function sum
    [1] 500500
    
    > fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
    Executing function dplyr::glimpse
     int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
    

    如果您希望消息作为字符向量,请将 message 替换为 print

    【讨论】:

      最近更新 更多