diff --git a/NEWS.md b/NEWS.md index b059427814..1cfbed786c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -28,6 +28,8 @@ 9. Sorting, grouping and finding unique values of a numeric column containing at most one finite value (such as `c(Inf,0,-Inf)`) could return incorrect results, [#3372](https://github.com/Rdatatable/data.table/issues/3372) [#3381](https://github.com/Rdatatable/data.table/issues/3381); e.g., `data.table(A=c(Inf,0,-Inf), V=1:3)[,sum(V),by=A]` would treat the 3 rows as one group. This was a regression in 1.12.0. Thanks to Nicolas Ampuero for reporting. +10. Quoted expression having `:=` and dot alias in RHS now works as expected. Thanks to @franknarf1 for raising up issue on [StackOverflow](https://stackoverflow.com/questions/41228076/using-data-tables-shortcut-in-quoted-expressions) and @jangorecki for PR. + #### NOTES 1. When upgrading to 1.12.0 some Windows users might have seen `CdllVersion not found` in some circumstances. We found a way to catch that so the [helpful message](https://twitter.com/MattDowle/status/1084528873549705217) now occurs for those upgrading from versions prior to 1.12.0 too, as well as those upgrading from 1.12.0 to a later version. See item 1 in notes section of 1.12.0 below for more background. diff --git a/R/data.table.R b/R/data.table.R index 13d62b4eba..6284585170 100644 --- a/R/data.table.R +++ b/R/data.table.R @@ -180,7 +180,7 @@ data.table <-function(..., keep.rownames=FALSE, check.names=FALSE, key=NULL, str replace_dot_alias <- function(e) { # we don't just simply alias .=list because i) list is a primitive (faster to iterate) and ii) we test for use # of "list" in several places so it saves having to remember to write "." || "list" in those places - if (is.call(e)) { + if (is.call(e) && !is.function(e[[1L]])) { # . alias also used within bquote, #1912 if (e[[1L]] == 'bquote') return(e) if (e[[1L]] == ".") e[[1L]] = quote(list) @@ -353,7 +353,10 @@ chmatch2 <- function(x, table, nomatch=NA_integer_) { jsub = eval(jsub[[2L]], parent.frame(), parent.frame()) # this evals the symbol to return the dynamic expression if (is.expression(jsub)) jsub = jsub[[1L]] # if expression, convert it to call # Note that the dynamic expression could now be := (new in v1.9.7) - root = if (is.call(jsub)) as.character(jsub[[1L]])[1L] else "" + root = if (is.call(jsub)) { + jsub = replace_dot_alias(jsub) + as.character(jsub[[1L]])[1L] + } else "" } if (root == ":=") { allow.cartesian=TRUE # (see #800) diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index b6f48c33db..e2aafc2e3f 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -13575,6 +13575,14 @@ A2,20180103,5.0,0 A2,20180104,5.0,0") test(1995.2, DT[, p1:=first(price[volume>0]), by=symbol]$p1, rep(c(11,NA), c(3,3))) +# quoted `:=` expression did not replace dot with list, #3425 +d = data.table(a=1L) +qcall = quote(b := .(2L)) +test(1996.1, d[, eval(qcall)], data.table(a=1L, b=2L)) +qcall = quote(b := .(.Primitive("sum")(1, 2))) # such calls can be issued by dcast +d = data.table(a=1L) +test(1996.2, d[, eval(qcall)], data.table(a=1L, b=3)) + ################################### # Add new tests above this line #