Moritz Schwarz
Moritz Schwarz

Reputation: 2489

R function - access all arguments including default arguments

I would like to access both the user chosen inputs of a function as well as all default arguments of a function.

example <- function(a = 1:10, b) {
  c = a + b

  output <- list()
  output$call <- sys.call()
  output$data <- c
  return(output)
}

example_output <- example(b=10)

I'm trying to use sys.call() to get the relevant information and I then store it as call in the output, but this only returns the information that the user inputted in the first place:

example_output
$call
example(b = 10)

$data
 [1] 11 12 13 14 15 16 17 18 19 20

Which still leaves me uncertain what a in this case is, as it was set by default in the function definition.

I know that I can get the default arguments using

formals(example)
$a
1:10

$b

which gives me the default values but not the user input.

I would like to save all this in the output object (a list in this case) so that it's saved for further processing of the object.

Any suggestions how this is possible?

Many thanks!

Upvotes: 0

Views: 125

Answers (2)

Moritz Schwarz
Moritz Schwarz

Reputation: 2489

This has been answered in another post (that I should have really found..).

This can be done using mget(names(formals()),sys.frame(sys.nframe())). Using this in a full example:

example <- function(a = 1:10, b) {
  c = a + b
  
  output <- list()
  output$call <- mget(names(formals()),sys.frame(sys.nframe()))
  output$data <- c
  return(output)
}

example(b=10)

gives me:

$call
$call$a
 [1]  1  2  3  4  5  6  7  8  9 10

$call$b
[1] 10


$data
 [1] 11 12 13 14 15 16 17 18 19 2

which is now the default argument as well as the user inputted arugment.

Thanks for your help @user63230!

Upvotes: 0

Allan Cameron
Allan Cameron

Reputation: 173793

I can't really think of an application for this, but it's certainly possible:

example <- function(a = 1:10, b) 
{
  default_args <- formals(example)
  mc           <- as.list(match.call())
  passed_vars  <- mc[-1]
  default_args <- default_args[is.na(match(names(default_args), names(passed_vars)))]
  for(i in seq_along(default_args)) 
    passed_vars[[names(default_args)[i]]] <- default_args[[i]]

  passed_vars <- passed_vars[match(names(formals(example)), names(passed_vars))]

  mc <- mc[1]

  for(i in seq_along(passed_vars)) 
    mc[[names(passed_vars)[i]]] <- passed_vars[[names(passed_vars)[i]]]

  c = a + b

  output <- list()
  output$call <- as.call(mc)
  output$data <- c
  return(output)
}

So we can do:

example(b=5)
#> $call
#> example(a = 1:10, b = 5)
#>
#> $data
#> [1]  6  7  8  9 10 11 12 13 14 15

and

example(a = 1:5, b=5)
#> $call
#> example(a = 1:5, b = 5)
#>
#> $data
#> [1]  6  7  8  9 10

Upvotes: 1

Related Questions