Skip to content

Commit e9087ce

Browse files
Nj221102nitish jhaMichaelChirico
authored
Improved Error Message for Assigning NULL to List Column Items (#6336)
* improved error message in assign * updated error * updated test * removed backticks * small fix * re-site NEWS entry * Improve NEWS wording * Improve error preciseness, add tests --------- Co-authored-by: nitish jha <[email protected]> Co-authored-by: Michael Chirico <[email protected]>
1 parent 3020933 commit e9087ce

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ rowwiseDT(
6969

7070
5. Some grouping operations run much faster under `verbose=TRUE`, [#6286](https://github.com/Rdatatable/data.table/issues/6286). Thanks @joshhwuu for the report and fix. This overhead was not present on Windows. As a rule, users should expect `verbose=TRUE` operations to run more slowly, as extra statistics might be calculated as part of the report; here was a case where the overhead was particularly high and the fix was particularly easy.
7171

72+
6. `set()` and `:=` now provide some extra guidance for common incorrect approaches to assigning `NULL` to some rows of a list column. The correct way is to put `list(list(NULL))` on the RHS of `:=` (or `.(.(NULL))` for short). Thanks to @MichaelChirico for the suggestion and @Nj221102 for the implementation.
73+
7274
# data.table [v1.16.0](https://github.com/Rdatatable/data.table/milestone/30) (25 August 2024)
7375

7476
## BREAKING CHANGES

inst/tests/tests.Rraw

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5580,9 +5580,14 @@ test(1352.7, DT[,sum(b),by=.(Grp=a%%2)], DT[,sum(b),by=list(Grp=a%%2)])
55805580
test(1352.8, DT[,sum(b),by=.(a%%2,c)], DT[,sum(b),by=list(a%%2,c)])
55815581

55825582
# that :=NULL together with i is now an error
5583-
DT = data.table(a=1:3, b=1:6)
5583+
DT = data.table(a=1:3, b=1:6, c=list(7, 8, 9, 8, 7, 6))
55845584
test(1353.1, DT[2, b:=NULL], error="When deleting columns, i should not be provided")
55855585
test(1353.2, DT[2, c("a","b"):=list(42, NULL)], error="When deleting columns, i should not be provided")
5586+
# #5526: friendlier error nudging to the correct way to sub-assign NULL to list columns
5587+
test(1353.3, DT[2, c := NULL], error="Invalid attempt to delete a list column.*did you intend to add NULL")
5588+
test(1353.4, DT[2, c := .(NULL)], error="Invalid attempt to delete a list column.*did you intend to add NULL")
5589+
test(1353.5, DT[2, `:=`(b=2, c=NULL)], error="Invalid attempt to delete a list column.*did you intend to add NULL")
5590+
test(1353.6, DT[2, d := NULL], error="Doubly-invalid attempt to delete a non-existent column while also providing i")
55865591

55875592
# order optimisation caused trouble due to chaining because of 'substitute(x)' usage in [.data.table.
55885593
set.seed(1L)
@@ -7246,7 +7251,7 @@ if (test_bit64) {
72467251
# fix for #1082
72477252
dt1 = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6), v=1:9, key=c("x", "y"))
72487253
dt2 = copy(dt1)
7249-
test(1502.1, dt1["a", z := NULL], error="When deleting columns, i should not be provided")
7254+
test(1502.1, dt1["a", z := NULL], error="Doubly-invalid attempt to delete a non-existent column while also providing i")
72507255
# this shouldn't segfault on 'dt1[...]'
72517256
test(1502.2, dt1["a", z := 42L], dt2["a", z := 42L])
72527257

src/assign.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,11 +467,17 @@ SEXP assign(SEXP dt, SEXP rows, SEXP cols, SEXP newcolnames, SEXP values)
467467
}
468468
coln--;
469469
SEXP thisvalue = RHS_list_of_columns ? VECTOR_ELT(values, i) : values;
470-
vlen = length(thisvalue);
471-
if (isNull(thisvalue) && !isNull(rows)) error(_("When deleting columns, i should not be provided")); // #1082, #3089
470+
if (isNull(thisvalue) && !isNull(rows)) {
471+
if (coln >= oldncol)
472+
error(_("Doubly-invalid attempt to delete a non-existent column while also providing i"));
473+
if (TYPEOF(VECTOR_ELT(dt, coln)) == VECSXP)
474+
error(_("Invalid attempt to delete a list column while also providing i; did you intend to add NULL to those rows instead? If so, use list_col := list(list(NULL)).")); // #5526
475+
error(_("When deleting columns, i should not be provided")); // #1082, #3089
476+
}
472477
if (coln+1 <= oldncol) colnam = STRING_ELT(names,coln);
473478
else colnam = STRING_ELT(newcolnames,coln-length(names));
474479
if (coln+1 <= oldncol && isNull(thisvalue)) continue; // delete existing column(s) afterwards, near end of this function
480+
vlen = length(thisvalue);
475481
//if (vlen<1 && nrow>0) {
476482
if (coln+1 <= oldncol && nrow>0 && vlen<1 && numToDo>0) { // numToDo > 0 fixes #2829, see test 1911
477483
error(_("RHS of assignment to existing column '%s' is zero length but not NULL. If you intend to delete the column use NULL. Otherwise, the RHS must have length > 0; e.g., NA_integer_. If you are trying to change the column type to be an empty list column then, as with all column type changes, provide a full length RHS vector such as vector('list',nrow(DT)); i.e., 'plonk' in the new column."), CHAR(STRING_ELT(names,coln)));

0 commit comments

Comments
 (0)