I'm trying to instrument some functions in R, by replacing them with my own versions which record some information and then call the original versions. My trouble is, how do I construct the call such that it exactly replicates the original arguments.
First, we'll set up an environment
env <- new.env()
One way I could do this is by getting the call and modifying it. However, I don't know how to do this with a primitive function.
## Option 1: get the call and modify it
env$`[` <- function(x, i, j, ...) {
my.call <- match.call()
## This isn't allowed.
my.call[[1]] <- as.name(.Primitive("["))
record.some.things.about(i, j)
eval(my.call, envir = parent.frame())
}
Alternatively, I could just get the arguments and use do.call
. However, I haven't worked out how to extract the arguments correctly.
## Option 2: do a call with the arguments
env$`[` <- function(x, i, j, ...) {
## This outputs a list, so if 'i' is missing, then 'j' ends up in the 'i' position.
## If I could get an alist here instead, I could keep 'j' in the right position.
my.args <- match.call()[-1]
record.some.things.about(i, j)
do.call(
.Primitive("["),
my.args,
envir = parent.frame()
)
}
Then, if we've done things right, we can eval some expression which uses [
inside the enviroment we've constructed, and our instrumented function will be called instead:
## Should return data.frame(b = c(4, 5, 6))
evalq(
data.frame(a = c(1, 2, 3), b = c(4, 5, 6))[, "b"],
envir = env
)
Can anyone help/advise?