如何绑定函数参数

发布于 2024-11-18 07:37:09 字数 306 浏览 2 评论 0原文

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

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

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

谢谢!

How do I partially bind/apply arguments to a function in R?

This is how far I got, then I realized that this approach doesn't work...

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

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小红帽 2024-11-25 07:37:09

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

它基本上通过生成一个匿名函数来工作,其方式与您自己构造部分绑定时的方式完全相同。

Here's a version of Curry that both preserves lazy evaluation of function argument, but constructs a function that prints moderately nicely:

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
}

It basically works by generating an anonymous function in exactly the same way you would if you were constructing the partial binding yourself.

缱绻入梦 2024-11-25 07:37:09

实际上,这似乎可以作为解决方法

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

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

Actually, this seems to work as a work around

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

However, ideally I want the bound arguments to disappear completely from the new function so that calls to the new function can happen with name specification, e.g. with add <- function(a,b) a+b I would like (bind(add,a=2))(1) to return 3.

紫竹語嫣☆ 2024-11-25 07:37:09

您是否尝试过查看 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

Have you tried looking at roxygen's Curry function?

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

Example usage:

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

Edit:
Curry is concisely defined to accept named or unnamed arguments, but partial application of fun to arguments by way of formal() assignment requires more sophisticated matching to emulate the same functionality. For instance:

> 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

Because the first argument in this function is still a, you need to specify which argument 2 is intended for (b=), or pass it as the second argument.

> oneplusb
function (a = 1, b) 
{
    a + 2 * b
}
> oneplusb(b=2) ## or oneplusb(,2)
[1] 5
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文