r-lib / rlang

Low-level API for programming with R
https://rlang.r-lib.org
Other
502 stars 140 forks source link

shallow copy don't work as expected #1666

Closed Yunuuuu closed 11 months ago

Yunuuuu commented 11 months ago

I have followed this thread to use shallow copy https://github.com/Rdatatable/data.table/issues/3214#issuecomment-462490046

  dt1 <- data.table::as.data.table(mtcars)
  (x <- names(dt1))
  # for shallow copy, mpg shouldn't be removed
  dt2 <- rlang::duplicate(dt1, shallow = TRUE)
  # for shallow copy, mpg shouldn't be removed
  dt3 <- dt1[TRUE]
  dt4 <- rlang::duplicate(dt1)

  dt4[, mpg := NULL]
  x
  names(dt1)
  dt3[, mpg := NULL]
  x
  names(dt1)
  dt2[, mpg := NULL]
  x
  names(dt1)
dt1 <- data.table::as.data.table(mtcars)
(x <- names(dt1))
#>  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
#> [11] "carb"
# for shallow copy, mpg shouldn't be removed
dt2 <- rlang::duplicate(dt1, shallow = TRUE)
# for shallow copy, mpg shouldn't be removed
dt3 <- dt1[TRUE]
dt4 <- rlang::duplicate(dt1)

dt4[, mpg := NULL]
x
#>  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
#> [11] "carb"
names(dt1)
#>  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
#> [11] "carb"
dt3[, mpg := NULL]
x
#>  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
#> [11] "carb"
names(dt1)
#>  [1] "mpg"  "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear"
#> [11] "carb"
dt2[, mpg := NULL]
x
#>  [1] "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"
names(dt1)
#>  [1] "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"

Created on 2023-11-06 with reprex v2.0.2

lionel- commented 11 months ago

I'm not sure what you're expecting here. But please note that rlang::duplicate() is for expert usage only. It's a direct wrapper around the C-level function of the R API which most certainly works as expected according to its specifications.

Yunuuuu commented 11 months ago

Thank you for the clarification. I understand that rlang::duplicate() is a powerful function that directly wraps a C-level function in the R API. I mean the names of dt1 shouldn't change when I change dt2 by reference just like what dt3 worked. dt3 is a data.table created via dt1[TRUE] which has been revealed to do shallow copy.

Yunuuuu commented 11 months ago

dt2 has removed the name "mpg" in dt1

dt2[, mpg := NULL]
x
#>  [1] "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"
names(dt1)
#>  [1] "cyl"  "disp" "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"
lionel- commented 11 months ago

It's not that it's powerful, it's that it's extremely low level, and you shouldn't expect any high level semantics from it. Also it's mostly meant for prototyping C code from R and should generally not be used in user or package code.

dt2 has removed the name "mpg" in dt1

Yes since it's a shallow copy the attributes list is not duplicated, which means that if you modify the names in place later on you'll get side effects. It's all working as expected from the perspective of these very low level tools.