简体   繁体   English

将R中的任意函数列表组合成新函数[元编程]

[英]Combining arbitrary list of functions in R into new function [meta-programming]

I want to take arbitrary list of functions that each take one argument, and turn them into one big function that runs each constituent function, one after the other, in order. 我想获取函数的任意列表,每个函数都带有一个参数,然后将它们变成一个大函数,依次运行每个组成函数。

For example, let's look at three functions ( f , g , h ) that take a single argument. 例如,让我们看一下采用单个参数的三个函数( fgh )。 I want to supply them as arguments to my function-combiner like so: 我想将它们作为参数提供给我的函数组合器,如下所示:

function_maker(f,g,h)

and have it output the following function: 并输出以下功能:

function(x) {
  f(x)
  g(x)
  h(x)
}

How would one do that? 一个人怎么做? The functions supplied as arguments don't "interact" with each other, I just want them to run sequentially with the final value returned by the newly-made function being whatever would be returned from evaluating them in that sequence. 作为参数提供的函数不会彼此“交互”,我只是希望它们按顺序运行,而新函数返回的最终值就是按该顺序求值所返回的值。

My primary worry is keeping all the environments, etc. correct, so that it the newly-made function will work in whichever environment it's called. 我主要担心的是保持所有环境等正确无误,以便新创建的函数可以在调用的任何环境中工作。

This is what I have so far, but I suspect that it's pretty fragile: 到目前为止,这是我所拥有的,但是我怀疑它非常脆弱:

f <- function(x) {
  print("this is f")
  x + 2
}
g <- function(x) {
  print("this is g")
  x + 4
}
h <- function(x) {
  print("this is h")
  x + 9
}

function_maker <- function(...) {
  l <- rlang::enexprs(...) %>%
    purrr::map(~substitute(zzzz(cond), c(zzzz=.)))
  e <- rlang::expr({!!!l})
  e <- rlang::expr(function(cond) !!e)
  rlang::eval_tidy(e)
}

fgh <- function_maker(f,g,h)
body(fgh)
fgh(2)

This seems to do the job: 这似乎可以完成工作:

function_maker <- function(...) {
  ret  <- function(x) {}
  for(f in list(...)) {
    n <- length(body(ret))
    body(ret)[(n+1):(n + length(body(f)) - 1)] <- body(f)[-1]
  }
  ret
}

Result: 结果:

> function_maker(f, g, h)
function (x)
{
    print("this is f")
    x + 2
    print("this is g")
    x + 4
    print("this is h")
    x + 9
}

Alternatively something simpler: 或者,一些更简单的方法:

function_maker <- function(...) {
  calls <- mapply(function(x) paste0(x, "(x)"), as.list(substitute(list(...)))[-1])
  as.call(c(as.name("{"), parse(text=calls)))
}

Which results in: 结果是:

> function_maker(f,g,h)
{
    f(x)
    g(x)
    h(x)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM