@@ -128,6 +128,35 @@ replace_dot_alias = function(e) {
128128 }
129129}
130130
131+ .assign_in_parent_exact = function (name , x , env , caller ) {
132+ k = eval(name [[2L ]], env , env )
133+ if (is.list(k )) {
134+ origj = j = if (name [[1L ]] == " $" ) as.character(name [[3L ]]) else eval(name [[3L ]], env , env )
135+
136+ if (caller == " [.data.table" ) {
137+ if (is.character(j )) {
138+ 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 ))
139+ j = match(j , names(k ))
140+ if (is.na(j )) internal_error(" item '%s' not found in names of list" , origj )
141+ }
142+ } else if (caller == " setDT" ) {
143+ if (length(j ) == 1L ) {
144+ if (is.character(j )) {
145+ j = match(j , names(k ))
146+ if (is.na(j ))
147+ stopf(" Item '%s' not found in names of input list" , origj )
148+ }
149+ }
150+ }
151+
152+ .Call(Csetlistelt , k , as.integer(j ), x )
153+ } else if (is.environment(k ) && exists(as.character(name [[3L ]]), k )) {
154+ assign(as.character(name [[3L ]]), x , k , inherits = FALSE )
155+ } else if (isS4(k )) {
156+ .Call(CsetS4elt , k , as.character(name [[3L ]]), x )
157+ }
158+ }
159+
131160" [.data.table" = function (x , i , j , by , keyby , with = TRUE , nomatch = NA , mult = " all" , roll = FALSE , rollends = if (roll == " nearest" ) c(TRUE ,TRUE ) else if (roll > = 0.0 ) c(FALSE ,TRUE ) else c(TRUE ,FALSE ), which = FALSE , .SDcols , verbose = getOption(" datatable.verbose" ), allow.cartesian = getOption(" datatable.allow.cartesian" ), drop = NULL , on = NULL , env = NULL , showProgress = getOption(" datatable.showProgress" , interactive()))
132161{
133162 # ..selfcount <<- ..selfcount+1 # in dev, we check no self calls, each of which doubles overhead, or could
@@ -1214,21 +1243,8 @@ replace_dot_alias = function(e) {
12141243 setalloccol(x , n , verbose = verbose ) # always assigns to calling scope; i.e. this scope
12151244 if (is.name(name )) {
12161245 assign(as.character(name ),x ,parent.frame(),inherits = TRUE )
1217- } else if (.is_simple_extraction(name )) { # TODO(#6702): use a helper here as the code is very similar to setDT().
1218- k = eval(name [[2L ]], parent.frame(), parent.frame())
1219- if (is.list(k )) {
1220- origj = j = if (name [[1L ]] == " $" ) as.character(name [[3L ]]) else eval(name [[3L ]], parent.frame(), parent.frame())
1221- if (is.character(j )) {
1222- 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 ))
1223- j = match(j , names(k ))
1224- if (is.na(j )) internal_error(" item '%s' not found in names of list" , origj ) # nocov
1225- }
1226- .Call(Csetlistelt ,k ,as.integer(j ), x )
1227- } else if (is.environment(k ) && exists(as.character(name [[3L ]]), k )) {
1228- assign(as.character(name [[3L ]]), x , k , inherits = FALSE )
1229- } else if (isS4(k )) {
1230- .Call(CsetS4elt , k , as.character(name [[3L ]]), x )
1231- }
1246+ } else if (.is_simple_extraction(name )) {
1247+ .assign_in_parent_exact(name , x , parent.frame(), caller = " [.data.table" )
12321248 } # TO DO: else if env$<- or list$<-
12331249 }
12341250 }
@@ -2971,24 +2987,8 @@ setDT = function(x, keep.rownames=FALSE, key=NULL, check.names=FALSE) {
29712987 if (is.name(name )) {
29722988 name = as.character(name )
29732989 assign(name , x , parent.frame(), inherits = TRUE )
2974- } else if (.is_simple_extraction(name )) {
2975- # common case is call from 'lapply()'
2976- k = eval(name [[2L ]], parent.frame(), parent.frame())
2977- if (is.list(k )) {
2978- origj = j = if (name [[1L ]] == " $" ) as.character(name [[3L ]]) else eval(name [[3L ]], parent.frame(), parent.frame())
2979- if (length(j ) == 1L ) {
2980- if (is.character(j )) {
2981- j = match(j , names(k ))
2982- if (is.na(j ))
2983- stopf(" Item '%s' not found in names of input list" , origj )
2984- }
2985- }
2986- .Call(Csetlistelt , k , as.integer(j ), x )
2987- } else if (is.environment(k ) && exists(as.character(name [[3L ]]), k )) {
2988- assign(as.character(name [[3L ]]), x , k , inherits = FALSE )
2989- } else if (isS4(k )) {
2990- .Call(CsetS4elt , k , as.character(name [[3L ]]), x )
2991- }
2990+ } else if (.is_simple_extraction(name )) {
2991+ .assign_in_parent_exact(name , x , parent.frame(), caller = " setDT" )
29922992 } else if (name %iscall % " get" ) { # #6725
29932993 # edit 'get(nm, env)' call to be 'assign(nm, x, envir=env)'
29942994 name = match.call(get , name )
0 commit comments