如何影响 R 中通过引用传递的对象?

How do I affect an object passed by reference in R?

我在 R 中使用 data.table 包。除其他外,data.table 导致 tables 通过引用传递。 Data.table 还支持通过 Ref 插入或删除列,所以你可以这样做...

library('data.table')

AddSquares<-function(DT){
  DT[,x2:=(x*x)]
}

DT<-data.table(x=1:3)
AddSquares(DT)

DT
   x x2
1: 1  1
2: 2  4
3: 3  9

x2 是在 DT byRef 中创建的,因此我不必 return 修改后的 table。容易生气。不幸的是,data.table 不支持插入或删除 byRef,所以会发生以下情况...

StripEvens<-function(DT){
  DT <- DT[x %% 2 != 0]
}

StripEvens(DT)

DT
   x x2
1: 1  1
2: 2  4
3: 3  9

<- 运算符按值工作,因此它在函数内部创建 DT 的副本。如果我不这样做,那么函数调用结束时 return DT 然后它是 'destroyed' 。如果我 do return DT 然后我可以找回看起来像我想要的方式的 table,但我已经通过制作副本完成了,这可能也路过Val.

问题来了。一旦 DT 被传递到我的函数 byRef 中,我如何让 R 继续在 DT byRef 上工作?同样,我如何让 R 将函数内部的 DT 视为对函数外部 DT 引用的同一对象的引用?这可能吗?

这会有点像 names(x) <- letters 那样做。也就是说,它看起来像是通过引用,但实际上并非如此。如果您关心的是语义而不是是否创建对象的副本,那么您可以这样做:

library(data.table)
DT1 <- data.table(x=1:3)

StripEvens<-function(DT) {
  x <- substitute(DT)
  if(is.name(x)) {
    DT.ext <- get(as.character(x), parent.frame(), inherits=FALSE)
    if(identical(DT, DT.ext)) {
      assign(as.character(x), DT[x %% 2 != 0], envir=parent.frame())
  } } 
  return(invisible(NULL))
}

StripEvens(DT1)
DT1

生产:

   x
1: 1
2: 3

这不是完全健壮的(即,如果对象实际上不在父框架中等,则中断),但可以通过一些工作变得健壮。更大的问题是对象实际上并没有被引用修改,而是被复制、修改和替换。正如其他人指出的那样,除非您用 C 语言编写函数,否则不可能通过引用进行实际修改。