Let's say I have a function f that takes a bunch of arguments, along with an optional extra argument.
f <- function(..., extra)
{
arglst <- lapply(quos(...), get_expr)
if(!missing(extra))
{
extra <- get_expr(enquo(extra))
arglst <- c(arglst, extra=extra)
}
arglst
## ... do something with argument list ... ##
}
f(a, extra=foo)
# [[1]]
# a
#
# $extra
# foo
Note that I don't want to evaluate the arguments as such, but I do want to get the expressions that were passed in, to be evaluated by other code down the line.
The new rlang package (which powers the next version of dplyr, to be released on CRAN Real Soon Now) provides extensive facilities for lazy evaluation which I'm using in f above. For example quos, get_expr and enquo are all functions from rlang.
In f, the part where I process extra is actually boilerplate code: I'll want to do this in other functions, not just in f. I don't want to rewrite it each time, so I thought I'd put it into its own function:
doExtra <- function(arglst, extra)
{
if(!missing(extra))
{
extra <- get_expr(enquo(extra))
arglst <- c(arglst, extra=extra)
}
arglst
}
f2 <- function(..., extra)
{
arglst <- lapply(quos(...), get_expr)
arglst <- doExtra(arglst, extra)
arglst
}
The problem is that when I do it this way, the value of extra that doExtra sees is what's passed in from f2, not the original:
f2(a, extra=foo)
# [[1]]
# a
#
# $extra
# extra
How can I modify f to isolate the boilerplate code, without getting the wrong result? I can do something like manipulate the environment of doExtra's calling frame directly, but that would be exceedingly ugly.