r - 如何以编程方式创建 R 函数?

标签 r function

Hadley Wickham最近在 r-devel mailing 上问了一个有趣的问题列表,并且无法在 StackOverflow 上找到关于该主题的现有问题,我认为它可能有用,因为它也存在于此处。

换句话说:

R 函数由三个元素组成:参数列表、主体和环境。我们能否通过这三个元素以编程方式构造一个函数?

(在上面的 r-devel 链接中的线程末尾提供了一个相当全面的答案。我会将此留给其他人自行重新创建各种解决方案的基准测试并将其作为答案提供,但请确保如果你这样做,请引用哈德利。如果几个小时后没有人站出来,我会自己做。)

最佳答案

这是对讨论的扩展 here .

我们的三个部分需要是一个参数列表、一个正文和一个环境。

对于环境,我们将默认使用 env = parent.frame()

我们并不真的想要一个常规的旧参数列表,所以我们使用 alist 它有一些不同的行为:

"...values are not evaluated, and tagged arguments with no value are allowed"

args <- alist(a = 1, b = 2)

对于正文,我们引用我们的表达式以获得调用:

body <- quote(a + b)

一个选择是将 args 转换为一个配对列表,然后简单地调用函数 function 使用 eval:

make_function1 <- function(args, body, env = parent.frame()) {
      args <- as.pairlist(args)
      eval(call("function", args, body), env)
}

另一种选择是创建一个空函数,然后用所需的值填充它:

make_function2 <- function(args, body, env = parent.frame()) {
      f <- function() {}
      formals(f) <- args
      body(f) <- body
      environment(f) <- env

      f
}

第三种选择是简单地使用as.function:

make_function3 <- function(args, body, env = parent.frame()) {
      as.function(c(args, body), env)
}

最后,这对我来说似乎与第一种方法非常相似,除了 我们正在使用一种稍微不同的习语来创建函数调用,使用 替换而不是调用:

make_function4 <- function(args, body, env = parent.frame()) {
      subs <- list(args = as.pairlist(args), body = body)
      eval(substitute(`function`(args, body), subs), env)
}


library(microbenchmark)
microbenchmark(
      make_function1(args, body),
      make_function2(args, body),
      make_function3(args, body),
      make_function4(args, body),
      function(a = 1, b = 2) a + b
    )

Unit: nanoseconds
                          expr   min      lq  median      uq    max
1 function(a = 1, b = 2) a + b   187   273.5   309.0   363.0    673
2   make_function1(args, body)  4123  4729.5  5236.0  5864.0  13449
3   make_function2(args, body) 50695 52296.0 53423.0 54782.5 147062
4   make_function3(args, body)  8427  8992.0  9618.5  9957.0  14857
5   make_function4(args, body)  5339  6089.5  6867.5  7301.5  55137

关于r - 如何以编程方式创建 R 函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32449028/

相关文章:

r - Shiny - 如何使用 ggiraph

r - 如何将单列列表转换为 R 中的项目矩阵?

c++ - 好友功能看不到私有(private)成员

function - SSRS在表头中使用函数

javascript - coffeescript定义函数(或方法)时,用 ":"和 "="分隔函数名和参数列表有什么区别?

javascript - 如何使用此 Javascript 解决方案在 Web 表单上的 div 之间正确切换?

r - 在R中如何绘制时间与日历日期的关系

r - 将脚注包装到第二行以适合 kable 中的表格(LaTeX .Rmd)

r - 如何向每个面板添加一条平均线是facet_grid()对象?

javascript - 为每个元素运行多次的 JQuery 函数