我如何装饰R中的函数?

How can I decorate a function in R?

我正在尝试检测 R 中的一些函数,方法是用我自己的版本替换它们,记录一些信息,然后调用原始版本。我的问题是,我如何构建调用以使其完全复制原始参数。

首先,我们将设置一个环境

   env <- new.env()

我可以做到这一点的一种方法是接到电话并对其进行修改。但是,我不知道如何使用原始函数来做到这一点。

## 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())
}

或者,我可以获取参数并使用 do.call。但是,我还没有弄清楚如何正确提取参数。

## 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()
    )
}

然后,如果我们做对了,我们可以在我们构建的环境中评估一些使用 [ 的表达式,然后调用我们的检测函数:

## 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
)

任何人都可以 help/advise?

你不能用三点 arg 捕获原始函数 args 的所有内容,然后传递给原始函数吗?

sum <- function(..., na.rm = TRUE) {
  print("my sum") # here is where you can "record some info"
  base::sum(..., na.rm = na.rm) # then call original function w/ ...
}

base::sum(5,5, NA)
##[1] NA

# your function
sum(5,5, NA)
##[1] "my sum"
##[1] 10

使用trace:

trace(`[.data.frame`, quote({print("hello!")}), at = 1) 
iris[1,]
#Tracing `[.data.frame`(iris, 1, ) step 1 
#[1] "hello!"
#  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1          5.1         3.5          1.4         0.2  setosa