Wasabi
Wasabi

Reputation: 3061

Partial functions keeping their signature

We can use purrr::partial to create partial functions:

f <- function(x, y) {
  print(x)
  print(y)
  return(invisible())
}

ff <- purrr::partial(f, y = 1)

ff(2)
#> [1] 2
#> [1] 1

Created on 2020-02-19 by the reprex package (v0.3.0)

This can often be quite useful, but has the unfortunate side-effect that the partialized function loses it's signature, which is replaced with an elipsis:

ff
#> <partialised>
#> function (...) 
#> f(y = 1, ...)

While programatically irrelevant, this leads to worse code legibility during development, where RStudio's "intellisense" can no longer aid us in remembering the names and/or order of arguments. So is there some other means of partializing which keeps the original signature (minus the partialized-away arguments), as below?

ff
#> <partialised>
#> function (x) 
#> f(y = 1, x)

Now, obviously this can be done manually, by defining a new function ff which is simply a wrapper around f with the desired arguments.

ff <- function(x) f(x, y = 1)

But this means any modifications to the signature of f need to be replicated to ff. So is there a "cleaner" way of partializing while keeping the signature?

Upvotes: 3

Views: 89

Answers (1)

Artem Sokolov
Artem Sokolov

Reputation: 13691

One option is to use rlang::fn_fmls() (or base::formals() equivalent) to explicitly give default values to the function arguments:

# If desired, create a copy of the function first: ff <- f
rlang::fn_fmls(f) <- purrr::list_modify( rlang::fn_fmls(f), y=1 )

args(f)
# function (x, y = 1) 

f(2)
# [1] 2
# [1] 1

Upvotes: 2

Related Questions