如何创建一个返回具有不同参数的函数的函数?

时间:2017-04-05 06:13:16

标签: r function arguments

我正在尝试在R中编写一个函数,它接受两个函数(使用可以被视为相同的参数定义),将它们相乘并返回在某个新点上评估的该积的积分。现在,乘法函数并不那么难,这里的问题在于,我不想评估参数x中的一个函数,而是在w/x中评估它,其中{{1}是新参数(但我只想在函数产品中执行此操作)。这是我的代码:

w

我知道 "%*f%" <- function(a,b) { force(a) force(b) function(x){a(x) * b(x)} } pdf_product <- function(pdf1, pdf2) { pdf3 <- function(x,w) {pdf2(w/x)} myfun <- function(x,w) { (1/abs(x)) %*f% pdf1(x) %*f% pdf3(x,w) } function(w) { sapply(w, function(w) { integrate(function(x) myfun(x,w), llim, ulim)$value }) } } pdf1 <- function(x) {1/(2-1)} #simple function example1 pdf2 <- function(x) {1/(6-3)} #simple function example2 llim <- 1 #lower limit integral ulim <- 2 #upper limit integral prod <- pdf_product(pdf1, pdf2) prod(4) #should evaluate to 0.09589402 的最后一部分正常工作,给定一个工作函数pdf_product(因为这是如何在R中运行二维函数的单个积分 - 但是如果我错了)。但是,如果我运行上面的代码,我会收到以下错误消息(带回溯):

myfun

我觉得这个错误与我在 Error in integrate(function(x) myfun(x, w), llim, ulim) : evaluation of function gave a result of wrong length 5. integrate(function(x) myfun(x, w), llim, ulim) 4. FUN(X[[i]], ...) 3. lapply(X = X, FUN = FUN, ...) 2. sapply(w, function(w) { integrate(function(x) myfun(x, w), llim, ulim)$value }) 1. prod(4) 定义pdf3时引入的“变量变量”有关,但我找不到修复它的方法。我尝试在pdf2返回的函数中使用着名的R三点原理,但这也不起作用。

1 个答案:

答案 0 :(得分:0)

所以,你的问题是你要组成两个函数,但这些函数可以有两个以上的参数。这可能很有用:

"%*f%" <- function(a,b, ...) {
  force(a)
  force(b)
  if (length(formals(args(a))) > 1L && 
      length(formals(args(b))) > 1L)
    stop("Only one function with additional parameters allowed.")
  if (length(formals(args(a))) == 1L && 
      length(formals(args(b))) > 1L)
    return(function(x, ...){a(x) * b(x, ...)})
  if (length(formals(args(a))) > 1L && 
      length(formals(args(b))) == 1L)
    return(function(x, ...){a(x, ...) * b(x)})
  if (length(formals(args(a))) == 1L && 
      length(formals(args(b))) == 1L)
    return(function(x){a(x) * b(x)})
  stop("Function without parameters passed")
}

(sign %*f% abs)(-5)
#[1] -5
(sign %*f% `+`)(-5, 1)
#[1] 4

请注意,如果两个函数都有多个参数,则需要设计一种不同的传递方式:

"%*f%" <- function(a,b, args1 = NULL, args2 = NULL) {
  stopifnot(is.list(args1) | is.null(args1))
  stopifnot(is.list(args2) | is.null(args2))
  force(a)
  force(b)
  if (length(formals(args(a))) > 1L && 
      length(formals(args(b))) > 1L)
    return(function(x, args1, args2) do.call(a, c(x, args1)) * do.call(b, c(x, args2)))
  #code for the other cases
}

(`^` %*f% `+`)(-5, list(2), list(1))
#[1] -100

如果你喜欢使用套装magrittr,你可能会更好地服务。