diff --git a/NEWS.md b/NEWS.md index 9421f96400..04a409c8c7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -72,6 +72,8 @@ 12. `print(..., col.names = 'none')` now correctly adapts column widths to the data content, ignoring the original column names and producing a more compact output, [#6882](https://github.com/Rdatatable/data.table/issues/6882). Thanks to @brooksambrose for the report and @venom1204 for the PR. +13. Reference to `.SD` in `...` arguments to `lapply()`, e.g. ``lapply(list_of_tables, `[`, j=.SD[1L])`` is evaluated correctly, [#2982](https://github.com/Rdatatable/data.table/issues/2982). Thanks @franknarf1 for the report and @MichaelChirico for the fix. + ### NOTES 1. The following in-progress deprecations have proceeded: diff --git a/R/cedta.R b/R/cedta.R index 83d92ec9dd..5722b5438c 100644 --- a/R/cedta.R +++ b/R/cedta.R @@ -39,6 +39,16 @@ cedta.pkgEvalsUserCode = c("gWidgetsWWW","statET","FastRWeb","slidify","rmarkdow } # nocov end +.any_sd_queries_in_stack = function(calls) { + for (ii in length(calls):1) { # nolint: seq_linter. As above. + if (!calls[[ii]] %iscall% "[") next + the_lhs = calls[[ii]][[2L]] + if (!is.name(the_lhs) || the_lhs != ".SD") next + return(TRUE) + } + FALSE +} + # cedta = Calling Environment Data.Table-Aware cedta = function(n=2L) { # Calling Environment Data Table Aware @@ -52,12 +62,15 @@ cedta = function(n=2L) { return(TRUE) } nsname = getNamespaceName(ns) + sc = sys.calls() ans = nsname=="data.table" || "data.table" %chin% names(getNamespaceImports(ns)) || # most common and recommended cases first for speed (nsname=="utils" && (exists("debugger.look", parent.frame(n+1L)) || - (length(sc<-sys.calls())>=8L && sc[[length(sc)-7L]] %iscall% 'example')) ) || # 'example' for #2972 - (nsname=="base" && all(c("FUN", "X") %chin% ls(parent.frame(n)))) || # lapply + (length(sc)>=8L && sc[[length(sc)-7L]] %iscall% 'example')) ) || # 'example' for #2972 + (nsname=="base" && # lapply + (all(c("FUN", "X") %chin% ls(parent.frame(n))) || + .any_sd_queries_in_stack(sc))) || (nsname %chin% cedta.pkgEvalsUserCode && .any_eval_calls_in_stack()) || nsname %chin% cedta.override || isTRUE(ns$.datatable.aware) || # As of Sep 2018: RCAS, caretEnsemble, dtplyr, rstanarm, rbokeh, CEMiTool, rqdatatable, RImmPort, BPRMeth, rlist diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index aceeb77f89..4e09bc8df6 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -21426,3 +21426,6 @@ test(2330.7, as.data.table(list(z), keep.rownames=TRUE), data.table(rn=rep("", 3 M <- matrix(1:6, nrow=3, dimnames=list(rep("", 3), c("V1", "V2"))) # test of list(M) for empty-rowname'd matrix input test(2330.8, as.data.table(list(M), keep.rownames=TRUE), data.table(rn=rep("", 3), V1=1:3, V2=4:6)) + +# .SD reference in '...' passed to lapply(FUN=) is recognized as data.table +test(2331, lapply(list(data.table(a=1:2)), `[`, j=.SD[1L]), list(data.table(a=1L)))