Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过引用传递函数时处理R data.table中的无效selfref_R_Data.table - Fatal编程技术网

通过引用传递函数时处理R data.table中的无效selfref

通过引用传递函数时处理R data.table中的无效selfref,r,data.table,R,Data.table,我的团队使用data.table编写了大量代码,我们偶尔会被“通过复制整个表来检测并修复无效的.internal.selfref…”警告所困扰。当一个数据表通过引用传递给一个函数时,这种行为会破坏我们的代码,我正试图找出如何处理它 假设我有一个函数,作为副作用将一列添加到data.table中——请注意,原始data.table不会返回 foo <- function(mydt){ mydt[, c := c("a", "b")] return(123) ) > x&l

我的团队使用data.table编写了大量代码,我们偶尔会被“通过复制整个表来检测并修复无效的.internal.selfref…”警告所困扰。当一个数据表通过引用传递给一个函数时,这种行为会破坏我们的代码,我正试图找出如何处理它

假设我有一个函数,作为副作用将一列添加到data.table中——请注意,原始data.table不会返回

foo <- function(mydt){
   mydt[, c := c("a", "b")]
   return(123)
)

> x<- data.table(a=c(1,2), b=c(3,4))
> foo(x) 
[1] 123
> x
   a b c
1: 1 3 a
2: 2 4 b

这至少让我们有机会发现问题,但对foo()的用户来说并不友好,因为这些输入可能被破坏的方式可能非常不透明。理想情况下,我希望能够纠正损坏的输入并维护foo()所需的功能。但我不知道该怎么做,除非我重新构造代码,使foo返回mydt并将其分配给调用范围中的x,这是可能的,但并不理想。有什么想法吗?

你应该阅读整个警告

那你会注意到的


在此之前,此data.table已由R复制(或使用structure()或类似工具手动创建)。避开钥匙@pteehan,好问题!在我看来,一个更干净的解决方案是在分配步骤本身恢复过度分配,并发出警告,基本上是说“不要这样做!”


这样做的方法是通过
[[是的,我知道它会创建一个副本。挑战是我不能保证我的代码的用户不会使用[[
> x<- data.table(a=c(1,2), b=c(3,4))
> x[["a"]] <- c(7,8)
> foo(x)
[1] 123
Warning message:
In `[.data.table`(mydt, , `:=`(c, c("a", "b"))) :
Invalid .internal.selfref detected and fixed by taking a copy ...

 > x
    a b
 1: 7 3
 2: 8 4
if(!data.table:::selfrefok(mydt)) stop("mydt is corrupt.")
foo <- function(x) {
   l <- substitute(x[,c := 'a'], as.list(match.call())['x']); 
   eval.parent(l)
   return(123)}

xx<- data.table(a=c(1,2), b=c(3,4))
xx[["a"]] <- c(7,8)
foo(xx)
# [1] 123
# Warning message: .....

# but it now works!
xx
#    a b c
# 1: 7 3 a
# 2: 8 4 a
`[[<-.data.table` <- function(x, i, j, value) {
    warning("Don't do this. Use := instead.")
    call = sys.call()
    call[[1L]] = `[[<-.data.frame`
    ans = copy(eval(call, envir=parent.frame()))
}

foo <- function(mydt) {
   mydt[, c := c("a", "b")]
   return(123)
}
x <- data.table(a = c(1,2), b = c(3,4))

x[["a"]] <- c(7,8)
# Warning message:
# In `[[<-.data.table`(`*tmp*`, "a", value = c(7, 8)) :
#   Don't do this. Use := instead.

data.table:::selfrefok(x)
# [1] 1

foo(x)
# [1] 123

x
#    a b c
# 1: 7 3 a
# 2: 8 4 b