diff --git a/NEWS.md b/NEWS.md index d0a8e8f5f7..cc98ebbe31 100644 --- a/NEWS.md +++ b/NEWS.md @@ -396,6 +396,8 @@ # 2: 2021-02-03 # was 18661 # 3: 4611686018427387906 # was error 'please use as.character' ``` + +47. `tables()` failed with `argument "..." is missing` when called from within a function taking `...`; e.g. `function(...) { tables() }`, [#5197](https://github.com/Rdatatable/data.table/issues/5197). Thanks @greg-minshall for the report and @michaelchirico for the fix. ## NOTES diff --git a/R/tables.R b/R/tables.R index 99c59f0c4d..adb82066b5 100644 --- a/R/tables.R +++ b/R/tables.R @@ -2,12 +2,13 @@ MB = NCOL = NROW = NULL tables = function(mb=TRUE, order.col="NAME", width=80, - env=parent.frame(), silent=FALSE, index=FALSE) + env=parent.frame(), silent=FALSE, index=FALSE) { # Prints name, size and colnames of all data.tables in the calling environment by default - all_obj = objects(envir=env, all.names=TRUE) - is_DT = which(vapply_1b(all_obj, function(x) is.data.table(get(x, envir=env)))) - if (!length(is_DT)) { + # include "hidden" objects (starting with .) via all.names=TRUE, but exclude ... specifically, #5197 + all_obj = grep("...", objects(envir=env, all.names=TRUE, sorted=order.col == "NAME"), invert=TRUE, fixed=TRUE, value=TRUE) + is_DT = vapply_1b(mget(all_obj, envir=env), is.data.table) + if (!any(is_DT)) { if (!silent) catf("No objects of class data.table exist in %s\n", if (identical(env, .GlobalEnv)) ".GlobalEnv" else format(env)) return(invisible(data.table(NULL))) } @@ -23,8 +24,11 @@ tables = function(mb=TRUE, order.col="NAME", width=80, KEY = list(key(DT)), INDICES = if (index) list(indices(DT))) })) - if (!order.col %chin% names(info)) stopf("order.col='%s' not a column name of info", order.col) - info = info[base::order(info[[order.col]])] # base::order to maintain locale ordering of table names + # objects() above handled the sorting for order.col=="NAME" + if (order.col != "NAME") { + if (!order.col %chin% names(info)) stopf("order.col='%s' not a column name of info", order.col) + info = info[base::order(info[[order.col]])] # base::order to maintain locale ordering of table names + } if (!silent) { # prettier printing on console pretty_format = function(x, width) { diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 6255f4f843..4ede2544c4 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -7490,7 +7490,8 @@ test(1536, duplicated(dt, incomparables=TRUE), error = "argument 'incomparables test(1537 , names(melt(dt, id.vars=1L, variable.name = "x", value.name="x")), c("x", "x.1", "x.2"), output = "Duplicate column names") # test for tables() -test(1538, tables(), output = "Total:") +test(1538.1, tables(), output = "Total:") +test(1538.2, !is.unsorted(tables(order.col="NROW")$NROW)) # uniqueN not support list-of-list: reverted #1224 d1 <- data.table(a = 1:4, l = list(list(letters[1:2]),list(Sys.time()),list(1:10),list(letters[1:2]))) @@ -18262,3 +18263,6 @@ for (fun in funs) { } test(testnum+0.01, DT[, prod(l), g], error="GForce prod can only be applied to columns, not .SD or similar.") +# tables() error when called from inside a function(...), #5197 +test(2221, (function(...) tables())(), output = "No objects of class data.table exist") +