【问题标题】:How to bind function arguments如何绑定函数参数
【发布时间】:2011-07-01 11:14:27
【问题描述】:

如何将参数部分绑定/应用到 R 中的函数?

这是我走了多远,然后我意识到这种方法行不通......

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

谢谢!

【问题讨论】:

  • 你想做什么?调用函数作为fun 传递,只有它的形式参数?如果是这样,如果fun 也有... 怎么办?
  • 如何找到 bunction 参数

标签: r bind apply


【解决方案1】:

这是 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
}

它基本上是通过生成一个匿名函数来工作的,就像你自己构建部分绑定一样。

【讨论】:

  • 有一天有机会在 plyr 看到这个吗?看来R-core不喜欢Curry,roxygen是个不方便的地方。
  • 否,但它可能出现在更高阶的函数包中。
  • 另外,roxygen 的下一个版本不会有它。
【解决方案2】:

实际上,这似乎可以解决问题

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

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

【讨论】:

  • 对,这比我用正式的匹配要好。
【解决方案3】:

你试过看 roxygen 的 Curry 函数吗?

> 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 被简洁地定义为接受命名或未命名的参数,但通过 formal() 赋值将fun 部分应用于参数需要更复杂的匹配来模拟相同的功能。例如:

> 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

【讨论】:

  • 不,我没有,感谢您的指点。 ` function (FUN, ...) { .orig = list(...) function(...) do.call(FUN, c(.orig, list(...))) }` 一个非常简单的解决方案...但是,这会从结果函数中完全删除名称...但我想通过该解决方案和上述解决方案可以涵盖两种情况。
  • 实际上,您仍然可以通过名称将参数传递给Curry -- 试试看:Curry(aplusb,b=2)(a=1)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
  • 2023-03-16
  • 2018-12-30
  • 1970-01-01
  • 2013-10-18
  • 1970-01-01
  • 2014-02-08
相关资源
最近更新 更多