Skip to content

Commit 1918128

Browse files
committed
Refactor do_j_names to reuse logic from setDT (#6702)
- Extract common code into new simple_extract() function.
1 parent 4f7f567 commit 1918128

File tree

1 file changed

+38
-30
lines changed

1 file changed

+38
-30
lines changed

R/data.table.R

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,42 @@ replace_dot_alias = function(e) {
936936
else
937937
x
938938
}
939+
# extract the same codes from setDT() and do_j_names() for #6702
940+
simple_extract <- function(name, x, checkSingleChar = TRUE, envir = parent.frame()) {
941+
k = eval(name[[2L]], envir, envir)
942+
if (is.list(k)) {
943+
origj = j = if (name[[1L]] == "$") {
944+
as.character(name[[3L]])
945+
} else {
946+
eval(name[[3L]], envir, envir)
947+
}
948+
if (is.character(j)) {
949+
if (checkSingleChar) {
950+
if (length(j) != 1L) {
951+
stopf("Cannot assign to an under-allocated recursively indexed list -- L[[i]][,:=] syntax is only valid when i is length 1, but its length is %d", length(j))
952+
}
953+
j2 = match(j, names(k))
954+
if (is.na(j2)) {
955+
internal_error("item '%s' not found in names of list", origj)
956+
}
957+
j = j2
958+
} else {
959+
if (length(j) == 1L) {
960+
j2 = match(j, names(k))
961+
if (is.na(j2)) {
962+
stopf("Item '%s' not found in names of input list", origj)
963+
}
964+
j = j2
965+
}
966+
}
967+
}
968+
.Call(Csetlistelt, k, as.integer(j), x)
969+
} else if (is.environment(k) && exists(as.character(name[[3L]]), k)) {
970+
assign(as.character(name[[3L]]), x, k, inherits = FALSE)
971+
} else if (isS4(k)) {
972+
.Call(CsetS4elt, k, as.character(name[[3L]]), x)
973+
}
974+
}
939975
# handle auto-naming of last item of j (e.g. within {} or if/else, #2478)
940976
# e.g. DT[, .(a=sum(v), v, .N), by=] should create columns named a, v, N
941977
do_j_names = function(q) {
@@ -1216,20 +1252,7 @@ replace_dot_alias = function(e) {
12161252
if (is.name(name)) {
12171253
assign(as.character(name),x,parent.frame(),inherits=TRUE)
12181254
} else if (.is_simple_extraction(name)) { # TODO(#6702): use a helper here as the code is very similar to setDT().
1219-
k = eval(name[[2L]], parent.frame(), parent.frame())
1220-
if (is.list(k)) {
1221-
origj = j = if (name[[1L]] == "$") as.character(name[[3L]]) else eval(name[[3L]], parent.frame(), parent.frame())
1222-
if (is.character(j)) {
1223-
if (length(j)!=1L) stopf("Cannot assign to an under-allocated recursively indexed list -- L[[i]][,:=] syntax is only valid when i is length 1, but its length is %d", length(j))
1224-
j = match(j, names(k))
1225-
if (is.na(j)) internal_error("item '%s' not found in names of list", origj) # nocov
1226-
}
1227-
.Call(Csetlistelt,k,as.integer(j), x)
1228-
} else if (is.environment(k) && exists(as.character(name[[3L]]), k)) {
1229-
assign(as.character(name[[3L]]), x, k, inherits=FALSE)
1230-
} else if (isS4(k)) {
1231-
.Call(CsetS4elt, k, as.character(name[[3L]]), x)
1232-
}
1255+
simple_extract(name, x, checkSingleChar = TRUE, envir = parent.frame())
12331256
} # TO DO: else if env$<- or list$<-
12341257
}
12351258
}
@@ -2962,22 +2985,7 @@ setDT = function(x, keep.rownames=FALSE, key=NULL, check.names=FALSE) {
29622985
assign(name, x, parent.frame(), inherits=TRUE)
29632986
} else if (.is_simple_extraction(name)) {
29642987
# common case is call from 'lapply()'
2965-
k = eval(name[[2L]], parent.frame(), parent.frame())
2966-
if (is.list(k)) {
2967-
origj = j = if (name[[1L]] == "$") as.character(name[[3L]]) else eval(name[[3L]], parent.frame(), parent.frame())
2968-
if (length(j) == 1L) {
2969-
if (is.character(j)) {
2970-
j = match(j, names(k))
2971-
if (is.na(j))
2972-
stopf("Item '%s' not found in names of input list", origj)
2973-
}
2974-
}
2975-
.Call(Csetlistelt, k, as.integer(j), x)
2976-
} else if (is.environment(k) && exists(as.character(name[[3L]]), k)) {
2977-
assign(as.character(name[[3L]]), x, k, inherits=FALSE)
2978-
} else if (isS4(k)) {
2979-
.Call(CsetS4elt, k, as.character(name[[3L]]), x)
2980-
}
2988+
simple_extract(name, x, checkSingleChar = FALSE, envir = parent.frame())
29812989
} else if (name %iscall% "get") { # #6725
29822990
# edit 'get(nm, env)' call to be 'assign(nm, x, envir=env)'
29832991
name = match.call(get, name)

0 commit comments

Comments
 (0)