Search code examples
rnsepryr

How can I get the values of all arguments used when evaluating a call object in a specified environment


say I have a function f as

f = function(x = 1, y, z, t) { x + y + z}

and a list l such

l = list(Y = 2, t = "test")

I can evaluate f in l like

eval(quote(f(y = Y, z = 3)), envir = l)
6

My question is that I'd like to get all the values of the arguments that ends up being used by the function f ie. a function magic that would take a call object and an environment and would return the values of all the arguments that would be used in evaluating the expression.

For instance:

call_obj = quote(f(y = Y, z = 3))
magic(call_obj, envir = l)
# I get a named list which value is list(1,2,3,"test")
# For that matter I do not even need the default arguments values (x)

EDIT: Adding a bounty for a base-r answer (while @Artem Sokolov provided a purrr-rlang one, extracting a couple relevant functions would still be fine though)


Solution

  • tidyverse solution

    # Identify the variables in l that can be used to specify arguments of f
    args1 <- l[ intersect( names(formals(f)), names(l) ) ]
    
    # Augment the call with these variables
    call_obj2 <- rlang::call_modify( call_obj, !!!args1 )
    # f(y = Y, z = 3, t = "test")
    
    # Evaluate the arguments of the call in the context of l and combine with defaults
    purrr::list_modify( formals(f),
                       !!!purrr::map(rlang::call_args(call_obj2), eval, l) )
    

    base R solution

    # As above
    args1 <- l[ intersect( names(formals(f)), names(l) ) ]
    
    # Augment the call with variables in args1
    l1 <- modifyList( as.list(call_obj), args1 )[-1]
    
    # Evaluate the arguments in the context of l and combine with defaults
    modifyList(formals(f), lapply(l1, eval, l))
    

    Output for both solutions

    # $x
    # [1] 1
    #
    # $y
    # [1] 2
    #
    # $z
    # [1] 3
    #
    # $t
    # [1] "test"