I am trying to wrap my head around a problem I ran into that I think largely revolves around environments, lazy evaluation and issues related to these things. I have a main function (foo1
below) that in my actual use case is quite extensive. For this reason I am trying to provide some wrapper functions (foo2
and foo3
) that modify specific elements of the main function.
My problem is that I in the end don't obtain actual values, but I obtain symbols. Can someone provide some guidance as to what I need to with environments and what not to get this sorted?
Here's my MWE:
foo1 <- function(foo, a, b, c=1, d=1) {
if (!missing(foo)) {
mcall <- as.list(match.call())[-(1:2)]
call_names <- names(mcall)
foo <- foo[-which(names(foo) %in% call_names)]
foo <- c(foo, mcall)
} else {
foo <- list(a=a, b=b, c=c, d=d)
}
return(foo)
}
foo2 <- function(a, b) {
foo1(a=a, b=b)
}
foo3 <- function(foo, c, d) {
foo1(foo, c=c, d=d)
}
f <- foo2(a=1, b=1)
f <- foo3(f, c=2, d=2)
str(f)
> str(f)
List of 4
$ a: num 1
$ b: num 1
$ c: symbol c
$ d: symbol d
Here I want c
and d
to be equal to 2
, but they are symbols.
When you use
match.call
, it prevents evaulation of the parameters. If you want to evaluate the parameters, then you need to explicitly do so. For exampleThis turns the call to
foo1
into a call tolist()
and evaluates the result. Another option would be just to usemget()
with the variables in the local environment that you want to capture. This will trigger the evaulation