如何绑定函数参数

时间:2011-07-01 11:14:27

标签: r bind apply

如何将参数部分绑定/应用于R?

中的函数

这是我有多远,然后我意识到这种方法不起作用......

bind <- function(fun,...)
{
  argNames <- names(formals(fun))
  bindedArgs <- list(...)
  bindedNames <- names(bindedArgs)
  function(argNames[!argNames %in% bindedArgs])
   {
   #TODO
  }
}

谢谢!

3 个答案:

答案 0 :(得分:8)

这是Curry的一个版本,它既保留了对函数参数的惰性求值,又构造了一个适度打印的函数:

Curry <- function(FUN, ...) {
  args <- match.call(expand.dots = FALSE)$...
  args$... <- as.name("...")

  env <- new.env(parent = parent.frame())

  if (is.name(FUN)) {
    fname <- FUN
  } else if (is.character(FUN)) {
    fname <- as.name(FUN)
  } else if (is.function(FUN)){
    fname <- as.name("FUN")
    env$FUN <- FUN
  } else {
    stop("FUN not function or name of function")
  }
  curry_call <- as.call(c(list(fname), args))

  f <- eval(call("function", as.pairlist(alist(... = )), curry_call))
  environment(f) <- env
  f
}

它基本上可以通过生成匿名函数来实现,就像您自己构建部分绑定一样。

答案 1 :(得分:4)

你试过看过roxygen的咖喱功能吗?

> library(roxygen) 
> Curry
function (FUN, ...) 
{
    .orig = list(...)
    function(...) do.call(FUN, c(.orig, list(...)))
}
<environment: namespace:roxygen>

使用示例:

> aplusb <- function(a,b) {
+   a + 2*b
+ }
> oneplusb <- Curry(aplusb,1)
> oneplusb(2)
[1] 5

修改 Curry被简明地定义为接受命名或未命名的参数,但通过fun赋值将formal()部分应用于参数需要更复杂的匹配来模拟相同的功能。例如:

> bind <- function(fun,...)
+ {
+   argNames <- names(formals(fun))
+   boundArgs <- list(...)
+   boundNames <- names(boundArgs)
+   if(is.null(boundNames)) {
+     formals(fun)[1:length(boundArgs)] <- boundArgs
+   } else {
+     formals(fun)[match(names(boundArgs),argNames)] <- boundArgs
+   }
+   fun
+ }
> oneplusb <- bind(aplusb,1)
> oneplusb(2)
Error in 2 * b : 'b' is missing

因为此函数中的第一个参数仍然是a,所以您需要指定哪个参数2用于(b=),或者将其作为第二个参数传递。

> oneplusb
function (a = 1, b) 
{
    a + 2 * b
}
> oneplusb(b=2) ## or oneplusb(,2)
[1] 5

答案 2 :(得分:4)

实际上,这似乎是一种解决方法

bind <- function(fun,...)
{
  boundArgs <- list(...)
  formals(fun)[names(boundArgs)] <- boundArgs
  fun
}

但是,理想情况下,我希望绑定参数完全从新函数中消失,以便可以使用名称规范调用新函数,例如使用add <- function(a,b) a+b我希望(bind(add,a=2))(1)返回3.