开发者

How to bind function arguments

开发者 https://www.devze.com 2023-03-16 21:52 出处:网络
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...

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 &开发者_运维技巧lt;- names(bindedArgs)
  function(argNames[!argNames %in% bindedArgs])
   {
   #TODO
  }
}

Thanks!


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.


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.


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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号