Can I access the full call of the current function with both default and user-supplied arguments?

I would like to access the current function call programatically with all arguments it is called with. Here is a reprex and the desired output:

library(rlang)

foo <- function(x, y = 3, ...) {
    call_frame()
}

foo(a = 5, b = 2)
#> <frame 29> (0)
#> expr: foo(a = 5, b = 2)
#> env:  [local 0x7ff7eec5ab90]

formals("foo")
#> $x
#> 
#> 
#> $y
#> [1] 3
#> 
#> $...

# desired:

expr(foo(y = 3, a = 2, b = 2))
#> foo(y = 3, a = 2, b = 2)

# or maybe

expr(foo(x = missing_arg(), y = 3, a = 2, b = 2))
#> foo(x = missing_arg(), y = 3, a = 2, b = 2)

Created on 2018-08-07 by the reprex package (v0.2.0).

I think I could do what I want with a combination of base::formals and rlang::call_frame but it would be quite difficult (handling default and missing arguments etc). So my question is: is there an easy way to do this? I could not find it neither in advanced R nor in rlang documentation but it is quite possible that I overlooked sg.

My ultimate motivation is to simplify functions where I call another function with almost exactly the same arguments with the help of rlang::call_modify.

I found a somewhat related question, but I still behave it is worth to have these separately: Checking if a function has been called with a default argument.

thanks a lot,
Ildi

2 Likes

I would use match.call().

f <- function(x = 1, y, ...) match.call()

f()
#> f()
f(3, 4)
#> f(x = 3, y = 4)
f(x = 3)
#> f(x = 3)
f(1, 2, 3, 4)
#> f(x = 1, y = 2, 3, 4)

Created on 2018-08-07 by the reprex
package
(v0.2.0).

Modelling functions do lots of call manipulation, especially those in the style of lm. The source of lm has some examples of how the call gets used.

Hi Alex,

thanks a lot, especially for the lm reference! Though match.call does not exactly do what I desire: it expands unnamed arguments to named arguments but does not include default value if it is not overridden:

f <- function(x = 1, y, ...) match.call()

f()
#> f()

f(3, 4)
#> f(x = 3, y = 4)

f(x = 3)
#> f(x = 3)

f(1, 2, 3, 4)
#> f(x = 1, y = 2, 3, 4)

f(y = 2)
#> f(y = 2)
# desired: f(x = 1, y = 2)

Created on 2018-08-08 by the reprex package (v0.2.0).