2015-11-20 6 views
2

Если я создаю среду со списком в ней и хочу присвоить значения этому списку, то почему при использовании get и assign происходит следующее:Присвоить индексу списка в конкретной среде с помощью `get`

res <- new.env() 
res$calls <- vector("list", 100) 
res$counter <- 1 

## works fine 
res$calls[[1]] <- 1 

## Fails, why? 
get("calls", envir=res)[[get("counter", envir=res)]] <- 2 

## doesnt make the assignment 
val <- get("calls", envir=res)[[get("counter", envir=res)]] 
assign("val", 2, envir=res) 
+0

Кромка: объекты, переданные по ссылке, изменяются ссылкой. 'DT = data.table (1); set (get ("DT"), j = 1L, value = 2) ', который работает, потому что' get ("DT") 'является просто указателем на' DT'/по существу является 'DT'. Тем не менее, не используйте 'get', а. – Frank

+0

Не уверен, что вы подразумеваете под «жестким кодом», но это отлично работает ... 'myfun = function (r, v) r [[" calls "]] [[r [[" counter "]]]] <- v; myfun (res, 2) 'просто расширив ответ ниже. По-моему, никто не предложил использовать '$'. – Frank

+0

Я бы посоветовал метапрограммировать (помещая имя каждого объекта в строку), но 'myfun ((get (" res ")), 3)' отлично подходит для этого, если вы считаете, что вам нужно это сделать. – Frank

ответ

3

Я думаю, что следующий будет решать проблему:

get("calls", envir=res)[[get("counter", envir=res)]] <- 2 терпит неудачу, потому что get не replacement функция. С другой стороны, res$calls[[1]] <- 1 на самом деле является функцией замены, которую вы можете увидеть, если вы наберете help('[[<-'). Это функция, используемая при выполнении задания. Я думаю, что причина, почему get не имеет замены, например, (get<-), заключается в том, что для этого существует определенная функция, которая называется assign (согласно комментарию @TheTime).

Для второго случая val <- get("calls", envir=res)[[get("counter", envir=res)]] создан в глобальной среде. При использовании assign("val", 2, envir=res) переменная res$val создается внутри res среды, которые вы можете увидеть ниже:

> res$val 
[1] 2 

Однако val остается тем же самым на глобальную окружающую среду, как 1:

> val 
[1] 1 

Таким образом, вы, вероятно, не сможет выполнить задание либо get, либо assign. get не допустит этого, потому что это не функция замены и правопреемник упоминает:

правопреемник не отправляет методы назначения, поэтому он не может быть использован для установки элементов векторов, имена, атрибуты и т.д.

Итак, вы можете использовать обычный метод назначения [[<-. @Frank в комментариях дает хороший способ:

res[[ "calls" ]][[ res[["counter"]] ]] <- 2 
+0

@TheTime Это то, что происходит, когда у вас есть data.table загружен :). Вы абсолютно правы, спасибо, – LyzandeR

+0

Вы не сможете сделать это с помощью 'get' или' assign'. 'get' не позволит этого, потому что это не функция замены, а упоминания'? assign': 'assign не отправляет методы назначения, поэтому он не может использоваться для установки элементов векторов, имен, атрибутов и т. д. Просто используйте обычный метод [[<<. – LyzandeR

+1

Спасибо @Frank, хороший. Я обновил. – LyzandeR

Смежные вопросы