Adicionando novas colunas a uma referência de data.table em uma função que nem sempre funciona

Ao escrever um pacote que depende dedata.table, Eu descobri um comportamento estranho. Eu tenho uma função que remove e reordena algumas colunas por referência e funciona muito bem, significando odata.table Eu passei foi modificado sem atribuir a saída da função. Eu tenho outra função que adicionaNovo colunas, no entanto, mas essas alterações nem sempre persistem nodata.table que foi passado.

Aqui está um pequeno exemplo:

library(data.table)  # I'm using 1.9.4
test <- data.table(id = letters[1:2], val=1:2)
foobar <- function(dt, col) {
    dt[, (col) := 1]
    invisible(dt)
}

test
#  id val
#1: a   1
#2: b   2
saveRDS(test, "test.rds")
test2 <- readRDS("test.rds")
all.equal(test, test2)
#[1] TRUE
foobar(test, "new")
test
#  id val new
#1: a   1   1
#2: b   2   1
foobar(test2, "new")
test2
#  id val
#1: a   1
#2: b   2

O que aconteceu? O que há de diferentetest2? Eu posso modificar as colunas existentes no local:

foobar(test, "val")
test
#  id val new
#1: a   1   1
#2: b   1   1
foobar(test2, "val")
test2
#  id val
#1: a   1
#2: b   1

Mas adicionando atest2 ainda não funciona:

foobar(test2, "someothercol")
.Last.value
#  id val someothercol
#1: a   1            1
#2: b   1            1
test2
#  id val
#1: a   1
#2: b   1

Não consigo identificar todos os casos em que vejo esse comportamento, mas salvar e ler no RDS é o primeiro caso que posso replicar com segurança. Escrever e ler de um CSV não parece ter o mesmo problema.

Esta é uma questão de ponteiro alaesse problema, como serializar uma tabela de dados destrói os ponteiros superalocados? Existe uma maneira simples de restaurá-los? Como posso procurá-los dentro da minha função, para restaurar os ponteiros ou erros, se a operação não funcionar?

Eu sei que posso atribuir a saída da função como uma solução alternativa, mas isso não é muitodata.table-y. Isso também não criaria uma cópia temporária na memória?

Resposta à solução de Arun

Arun instruiu que é realmente um problema de ponteiro, que pode ser diagnosticado comtruelength e consertado comsetDT oualloc.col. Encontrei um problema ao encapsular sua solução em uma função (continuando no código acima):

func <- function(dt) {if (!truelength(dt)) setDT(dt)}
func2 <- function(dt) {if (!truelength(dt)) alloc.col(dt)}
test2 <- readRDS("test.rds")
truelength(test2)
#[1] 0
truelength(func(test2))
#[1] 100
truelength(test2)
#[1] 0
truelength(func2(test2))
#[1] 100
truelength(test2)
#[1] 0

Portanto, parece que a cópia local dentro da função está sendo modificada corretamente, mas a versão de referência não. Por que não?

questionAnswers(1)

yourAnswerToTheQuestion