fun1、fun2和fun3似乎如出一辙:
fun1 <- function(fun, x) {
  fun(x)
}
fun1(mean, 1:10)
fun1(as.character, 1:10)
fun1(notafun, 1:10)
fun2 <- function(fun, x) {
  fun <- match.fun(fun)
  fun(x)
}
fun2(mean, 1:10)
fun2(as.character, 1:10)
fun2(notafun, 1:10)
fun3 <- function(fun, x) {
  fun <- deparse(substitute(fun))
  do.call(fun, list(x))
}
fun3(mean, 1:10)
fun3(as.character, 1:10)
fun3(notafun, 1:10)一般情况下,有一种策略是可取的吗?到目前为止,我只注意到如果将match.fun指定为字符串,fun也可以工作。
我的用例是包中用于本地使用的非导出函数(如果不能将fun指定为字符串,它不是一个限制)。使用match.fun而不是“直接”提供函数有什么好处(如在fun1中)。
发布于 2021-11-27 05:25:21
首先是文件!以下是?match.fun的相关章节
在调用以函数为参数的内部函数时,提取所需的函数对象,同时避免与其他类型的对象进行不期望的匹配。如果
FUN是一个函数,则返回它。如果它是一个符号(例如,用反引号括起来)或长度为1的字符向量,则将在调用者的父环境中使用get查找它。
因此,match.fun有两个主要好处:
fun2的文档就可以知道它的参数fun必须指定一个函数。它提供了这些好处,而几乎不需要付出性能代价:
x1 <- mean
x2 <- "mean"
x3 <- quote(mean)
microbenchmark::microbenchmark(match.fun(x1), match.fun(x2), match.fun(x3), times = 1000L)
# Unit: nanoseconds
#           expr  min   lq     mean median   uq  max neval
#  match.fun(x1)  287  328  362.481    328  328 1681  1000
#  match.fun(x2) 1599 1681 1820.892   1681 1763 7544  1000
#  match.fun(x3) 1599 1640 1783.049   1681 1722 7339  1000由于这些原因,在尝试评估函数调用(如在match.fun中)之前,使用fun2进行验证几乎总是比等待和希望可以评估调用(如fun1和fun3)要好。即使您的函数没有导出,即使您从未传递字符串或符号,这个原则仍然有效,因为透明性(参见2)使您的源代码更易于阅读和维护。
您的fun3是唯一的,因为它允许用户传递未计算的表达式,但由于多种原因,这种方法是有问题的:
,
base::mean(1:10)中的错误:无法找到函数“base::fun3(函数(X)平均(X),1:10) #function(x) mean(x)中的错误( 1:10):#找不到函数“函数(X)平均(X)”fun3(match.fun(平均值),1:10)#match.fun(mean)中的错误(1:10):#找不到函数match.fun(mean)deparse(substitute(fun))的结果是一个字符串,命名一个从调用环境中可以访问的函数,那么首先不需要deparse(substitute(fun)),因为fun无论如何都会对该函数进行评估。微基准::微基准(fun1(平均数,1:10),fun3(平均,1:10),时间= 1000 L)#单位:微秒# expr min lq平均中位数uq max内维尔#fun1(平均数,1:10) 2.009 2.378 2.700055 2.460 2.788 14.350 1000#fun3(平均,1:10) 9.020 10.127 10.991813 10.701 480 11.52.398 1000
总之,无论何时将函数作为参数使用match.fun都是很好的做法。如果您希望接受函数而不是字符串或符号,则可以避免match.fun,但在这种情况下,进行测试仍然是一种良好的实践:
function(FUN, ...) {
  if (!is.function(FUN)) {
    stop("oops")
  }
  ## do stuff
}https://stackoverflow.com/questions/70129354
复制相似问题