How to extract default value set inside a function?

Viewed 76

I have created the function toy_fun, and I am setting the default value of c inside the function.:

toy_fun = function(a,b,c) {
  
  if(missing(c)) c = 1
  sum <- a + b + c
  sum
}

Indeed, if I call toy_fun with only two arguments, I get:

toy_fun(1,1)
#> [1] 3

Now imagine that I can't access toy_fun's script but I still want to know, after the fact, what are the arguments of toy_fun and what are their assigned and default values, if any.

I have tried the following approach, from this post, but it does not gives me the value of c:

library(rlang)

fun_call <- quo(toy_fun(1,1))

default_args <- fn_fmls(call_fn(fun_call))
str(default_args)
#> Dotted pair list of 3
#>  $ a: symbol 
#>  $ b: symbol 
#>  $ c: symbol

user_args <- call_args(call_standardise(fun_call))
str(user_args)
#> List of 2
#>  $ a: num 1
#>  $ b: num 1

calling_args <- purrr::list_modify(default_args, user_args)
str(calling_args)
#> Dotted pair list of 3
#>  $ a:List of 2
#>   ..$ a: num 1
#>   ..$ b: num 1
#>  $ b: symbol 
#>  $ c: symbol

Question

Is there a way of knowing what the value of c was set to?

Created on 2021-03-26 by the reprex package (v0.3.0)

1 Answers

I'm going to make the simplifying assumption that you just want to know what the arguments are at the end of the function. Consequently, if c is being modified again after the initial check for it being missing, this approach will capture that change as well.

myEnv <- new.env()

trace(
  toy_fun, 
  print = FALSE,
  exit = quote(
    assign(
      "fxArgs", 
      mget(names(formals(toy_fun))),
      envir = myEnv
    )
  )
)

trace modifies functions to run arbitrary code. In this case it will be code to capture the argument values and save them to an environment where they can be accessed later via myEnv$fxArgs.

Working from the inside outwards, names(formals(toy_fun)) creates a character vector of the argument names so mget can retrieve them from the local function execution environment. These values are assigned to a predefined environment to take advantage of the pass-by-reference nature of environments. trace modifies toy_fun to execute this code on exit.

If you don't want later changes to c, you'll have to either know your specific function or find a way to find the line where it's first assigned. Once you know the line, you can add the trace after that line instead of on exit.

Related