Search code examples
rfunctionpartial-application

How to efficiently partially apply a function in R?


Suppose I have a function in R that takes multiple arguments, and I'd like to reduce it to a function of fewer arguments by setting some of the arguments to pre-specified values. I'm trying to figure out what is the best way to do this is in R.

For example, suppose I have a function

f <- function(a,b,c,d){a+b+c+d}

I'd like to create or find a function partial that would do the following

partial <- function(f, ...){
#fill in code here
}
new_f <- partial(f, a=1, c= 2)

new_f would be a function of b and d and would return 1+b+2+d

In python I would do

from functools import partial

def f(a,b,c,d):
    return a+b+c+d

new_f = partial(f, a=1, c= 2)

I'm actually doing this repeatedly and so I need for this to be as efficient as possible. Can anyone point me to the most efficient way to do this? Right now the best I can do is

partial <- function(f, ...){
    z <- list(...)
    formals(f) [names(z)] <- z
    f
}

Can anyone let me know of a faster way or the best way to do this? This is simply too slow.


Solution

  • There are functions in the pryr package that can handle this, namely partial()

    f <- function(a, b, c, d) a + b + c + d 
    pryr::partial(f, a = 1, c = 2)
    # function (...) 
    # f(a = 1, c = 2, ...)
    

    So you can use it like this -

    new_fun <- pryr::partial(f, a = 1, c = 2)
    new_fun(b = 2, d = 5)
    # [1] 10
    ## or if you are daring ...
    new_fun(2, 5)
    # [1] 10
    

    You could also simply change f()'s formal arguments with

    f <- function(a, b, c, d) a + b + c + d 
    formals(f)[c("a", "c")] <- list(1, 2)
    f
    # function (a = 1, b, c = 2, d) 
    # a + b + c + d
    f(b = 2, d = 5)
    # [1] 10
    

    But with the latter, you must name the b and d arguments in f() to avoid an error when you want to leave a and c as their default values.