Search code examples
rdata.tabler-package

Extend `[` method of data.table without breaking `head`


Problem: Wrapping [.data.table seems to disable some print to console operations like head.

Question: Is there a way to modify [.blarg so that head(b) will print to console? Or do I need to write a print.blarg method or something similar?

Context: I'm trying to lightly extend data.table (see blarg) so that I can wrap [.data.table to identify and modify certain objects passed in j (a simplistic version of that is provided in [.blarg. This is occurring within an R-package development framework. I've included an example head.blarg function, but while this seems to work in a normal environment, it doesn't work as part of a package. See the bottom of the post for code to try out the package environment.

library('data.table')

blarg <- function(...){
  r = data.table::data.table(...)
  data.table::setattr(r, 'class', c('blarg', class(r)))
  r
}

"[.blarg" <- function(x, i, j, by, ...){
  mc <- match.call()
  mc[[1]] <- quote(data.table:::`[.data.table`)
  res = eval.parent(mc)
}
a = data.table(1:10)
b = blarg(1:10)

#Prints to console
head(a)
#>    V1
#> 1:  1
#> 2:  2
#> 3:  3
#> 4:  4
#> 5:  5
#> 6:  6

#Does not print to console-- THIS IS THE PROBLEM BIT
head(b)

#But something is being returned
b1 <- head(b)
print(b1)
#>    V1
#> 1:  1
#> 2:  2
#> 3:  3
#> 4:  4
#> 5:  5
#> 6:  6

#' Specifically provide a head definition modeled off of head.data.table
#' @noRd
#' @importFrom utils head
#' @exportS3Method
head.blarg <- function (x, n = 6L, ...) 
{
  #cat('blarg')
  stopifnot(length(n) == 1L)
  i = seq_len(if (n < 0L) max(nrow(x) + n, 0L) else min(n, 
                                                        nrow(x)))
  x[i, , ]
}

#This prints to console, but not when as part of a package  
head(b)
#>    V1
#> 1:  1
#> 2:  2
#> 3:  3
#> 4:  4
#> 5:  5
#> 6:  6


sessionInfo()
#> R version 4.1.1 (2021-08-10)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 19043)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_United States.1252 
#> [2] LC_CTYPE=English_United States.1252   
#> [3] LC_MONETARY=English_United States.1252
#> [4] LC_NUMERIC=C                          
#> [5] LC_TIME=English_United States.1252    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] data.table_1.14.1
#> 
#> loaded via a namespace (and not attached):
#>  [1] ps_1.6.0          digest_0.6.27     withr_2.4.2       magrittr_2.0.1   
#>  [5] reprex_2.0.1      evaluate_0.14     highr_0.9         stringi_1.6.1    
#>  [9] rlang_0.4.11      cli_2.5.0         rstudioapi_0.13   fs_1.5.0         
#> [13] rmarkdown_2.8     tools_4.1.1       stringr_1.4.0     glue_1.4.2       
#> [17] xfun_0.23         yaml_2.2.1        compiler_4.1.1    htmltools_0.5.1.1
#> [21] knitr_1.33

As part of a package:

devtools::install_github('dcaseykc/headdtest')
source('https://raw.githubusercontent.com/dcaseykc/headdtest/main/exmple.R')
head(a) # Will print to console
head(b) # Probably won't print to console

Solution

  • After some more testing, changing [.blarg to explicitly return res seems to work.

    "[.blarg" <- function(x, i, j, by, ...){
      mc <- match.call()
      mc[[1]] <- quote(data.table:::`[.data.table`)
      res = eval.parent(mc)
    
      return(res)
    
    }