Skip to content
Open
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@
19. Ellipsis elements like `..1` are correctly excluded when searching for variables in "up-a-level" syntax inside `[`, [#5460](https://github.com/Rdatatable/data.table/issues/5460). Thanks @ggrothendieck for the report and @MichaelChirico for the fix.
20. `rowwiseDT()` now provides a helpful error message when a complex object that is not a list (e.g., a function) is provided as a cell value, instructing the user to wrap it in `list()`. [#7219](https://github.com/Rdatatable/data.table/issues/7219). Thanks @kylebutts for the report and @venom1204 for the fix.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
20. `rowwiseDT()` now provides a helpful error message when a complex object that is not a list (e.g., a function) is provided as a cell value, instructing the user to wrap it in `list()`. [#7219](https://github.com/Rdatatable/data.table/issues/7219). Thanks @kylebutts for the report and @venom1204 for the fix.
20. `rowwiseDT()` now provides a helpful error message when a complex object that is not a list (e.g., a function) is provided as a cell value, instructing the user to wrap it in `list()`, [#7219](https://github.com/Rdatatable/data.table/issues/7219). Thanks @kylebutts for the report and @venom1204 for the fix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ofc, it must also be moved to the 1.18.99 NEWS section

### NOTES
1. The following in-progress deprecations have proceeded:
Expand Down
15 changes: 15 additions & 0 deletions R/rowwiseDT.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ rowwiseDT = function(...) {
nrows = length(body) %/% ncols
if (length(body) != nrows * ncols)
stopf("There are %d columns but the number of cells is %d, which is not an integer multiple of the columns", ncols, length(body))
is_problematic = vapply_1b(
body,
function(v) !(is.atomic(v) || is.null(v) || typeof(v) == "list")
)
if (any(is_problematic)) {
first_problem_idx = which(is_problematic)[1L]
col_idx = (first_problem_idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[first_problem_idx]])
Comment on lines +21 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
first_problem_idx = which(is_problematic)[1L]
col_idx = (first_problem_idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[first_problem_idx]])
idx = which(is_problematic)[1L]
col_idx = (idx - 1L) %% ncols + 1L
col_name = header[col_idx]
obj_type = class1(body[[idx]])

Would feel more consistent to our codebase/

stopf(
"In column '%s', received an object of type '%s'.\nComplex objects (like functions, formulas, or calls) must be wrapped in list() to be stored in a data.table column.\nPlease use `list(...)` for this value.",
Copy link
Member

@ben-schwen ben-schwen Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The indent is off, see e.g.

> rowwiseDT(x =, func =, 1, \(x) x + 1)
Error in rowwiseDT(x = , func = , 1, function(x) x + 1) : 
  In column 'func', received an object of type 'function'.
Complex objects (like functions, formulas, or calls) must be wrapped in list() to be stored in a data.table column.
Please use `list(...)` for this value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also something more in the direction of

stopf("Column '%s' is type '%s'. Non-atomic, non-list objects must be wrapped in list(), e.g., list(f) instead of f", col_name, obj_type)

col_name,
obj_type
)
}
# make all the non-scalar elements to a list
needs_list = lengths(body) != 1L
body[needs_list] = lapply(body[needs_list], list)
Expand Down
13 changes: 13 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -21655,3 +21655,16 @@ local({
...123 = 'a'
test(2339.11, DT[, .....123], DT)
})

# rowwiseDT() valid and invalid handling of complex objects #7219
test(2340.1, rowwiseDT(x =, y =, 1, 2, 3, 4), data.table(x = c(1, 3), y = c(2, 4)))
test(2340.2, rowwiseDT(x =, func =,
1, list(\(x) x + 1),
2, list(function(z) z * 2)),
data.table(x = c(1, 2), func = list(\(x) x + 1, function(z) z * 2)))
test(2340.3, rowwiseDT(x =, func =, 1, \(x) x + 1),
error = "In column 'func', received an object of type 'function'.*wrap.*list")
test(2340.4, rowwiseDT(x =, expr =, 1, quote(a + b)),
error = "In column 'expr', received an object of type 'call'.*wrap.*list")
test(2340.5, rowwiseDT(x =, plist =, 1, as.pairlist(list(123))),
error = "In column 'plist', received an object of type 'pairlist'.*wrap.*list")
Loading