Anna Nevison
Anna Nevison

Reputation: 2759

Is there an R equivalent of Python's '*'?

In python you can do:

val = [1, 2, 3]

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

f(*val)

>>>6

But is there an R equivalent to passing a list/vector to a function and having it unpack the list/vector as the arguments to the function?

val <- c(1, 2, 3)
f <- function(a, 
              b, 
              c) {
     a+b+c
     }
#f(*val)

Upvotes: 4

Views: 794

Answers (2)

G. Grothendieck
G. Grothendieck

Reputation: 269965

Base R

do.call In R it is do.call. The first argument is the function or a character string giving the name of the function and the second argument is a list whose components will be passed as individual arguments to the function. No packages are used.

val <- c(1, 2, 3)
f <- function(a, b, c) a+b+c
do.call("f", as.list(val))
## [1] 6

Reduce Another approach is to curry f creating a new function with the first argument fixed, repeatedly doing so using Reduce to handle each successive argument. No packages are used.

Reduce(function(f, x, ...) function(...) f(x, ...), val, init = f)()
## [1] 6

purrr package

invoke The purrr package has invoke which basically just calls do.call but it will also convert the second argument to a list if it is not already a list:

library(purrr)
invoke(f, val)
## [1] 6

lift purrr also has lift which will convert a function that takes individual arguments to a new function that takes a list or vector. It also wraps do.call

lift(f)(val)
## [1] 6

partial purrr also has partial which will curry the function creating a new function with the first argument fixed taking only the remaining arguments so using reduce (also in purrr) to repeatedly invoke such currying:

reduce(val, partial, .init = f)()
## [1] 6

functional package

Curry Curry from the functional package could also be used to fix the first argument. When used together with Reduce from base R to repeatedly apply Curry it gives the same result. Note that Curry uses do.call internally.

library(functional)
Reduce(Curry, init = f, val)()
## [1] 6

Upvotes: 11

Artem Sokolov
Artem Sokolov

Reputation: 13701

Another option is to lift the domain of a function using lift() from the purrr package. Your definition of f takes multiple arguments, which in R terms is known as "dots". You can change its signature to accept a vector instead:

f2 <- purrr::lift_dv(f)
f2(val)
## [1] 6

# Or as a one-liner
purrr::lift_dv(f)(val)

Upvotes: 2

Related Questions