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

时间:2015-04-02 17:49:10

标签: r memory data.table pass-by-reference

我在R中使用data.table包。其中,data.table导致表通过引用传递。 Data.table还支持插入或删除byRef列,因此你可以做这样的事情......

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中创建的,所以我没有必要返回修改后的表。容易脱皮。很遗憾,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的副本。如果我从那时起不再返回DT,那么它就会被销毁掉#39;当函数调用结束时。如果我返回DT,那么我可以找回一个看起来像我想要的方式的表,但我已经通过制作一个副本来完成,这可能也是通过byVal。

所以这就是问题所在。一旦DT传递给我的函数byRef,我如何让R继续在DT byRef上工作?同样,如何让R将函数内部的DT视为对函数外部DT引用的同一对象的引用?这甚至可能吗?

1 个答案:

答案 0 :(得分:3)

这将以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编写函数,否则实际的参考修改是不可能的。