Вы путаете «среду вызова» с «окружающей средой». Ознакомьтесь с этими терминами в книге Хэдли «Advanced R.»
http://adv-r.had.co.nz/Environments.html
«Среда вызова» - это среда, из которой была вызвана функция, и она возвращено к сожалению названной функцией parent.frame
. Однако вызывающая среда не используется для лексической области видимости.
«Окружающая среда» - это среда, в которой была создана функция и которая используется для лексической области видимости. Вы создали как func1
, так и func2
в глобальной среде. Таким образом, глобальная среда является «окружающей средой» для обеих функций и будет использоваться для лексической области видимости независимо от среды вызова !!
Если вы хотите func2
использовать выполнение В среде func1
для лексической области видимости у вас есть (как минимум) два варианта. Вы можете создать func2
в пределах func1
func1 <- function(vec) {
func2 <- function(foos) {
for (foo in foos)
print(eval(parse(text = foo)))
return(foos)
}
text3_obj <- 'text3'
vec <- c(vec, c('text3_obj'))
return(func2(vec))
}
, тогда ваш тест будет работать как положено:
> text1_obj <- 'text1'
> text2_obj <- 'text2'
> func1(c('text1_obj', 'text2_obj'))
[1] "text1"
[1] "text2"
[1] "text3"
[1] "text1_obj" "text2_obj" "text3_obj"
В качестве альтернативы, вы можете создать func2
и переназначить его "замкнутую среду" из func1
.
func2 <- function(foos) {
for (foo in foos)
print(eval(parse(text = foo)))
return(foos)
}
func1 <- function(vec) {
text3_obj <- 'text3'
vec <- c(vec, c('text3_obj'))
environment(func2) <- environment()
return(func2(vec))
}
Это также будет работать, как и ожидалось.
Интересный лакомый кусочек, который я обнаружил во время написания демонстрационного кода ... Похоже, что когда вы переназначаете в среде func2
изнутри func1
, R создает копию func2
в среде выполнения func1
. К тому времени, когда вы вернетесь к консоли, окружающая среда исходного func2
останется неизменной. Свидетель:
a = function() {
print(identical(environment(a), globalenv()))
}
b = function(x) {
environment(a) <- environment()
a()
}
Тест a()
и b()
:
> a()
[1] TRUE
> b()
[1] FALSE
> a()
[1] TRUE
>
Это было не то, что я ожидал, но, похоже, действительно отличное поведение со стороны R. Если это в противном случае окружающая среда a()
была бы навсегда изменена на среду выполнения b()
, и FALSE
должен был бы быть возвращен при втором вызове a()
.
Если Оказывается, вы можете принудительно изменить исходное значение a()
в глобальной среде, используя <<-
:
a = function() {
print(identical(environment(a), globalenv()))
}
b = function(x) {
# set a variable in the execution environment of b() for use later...
montePython = "I'm not dead yet!!"
# change the enclosing environment of a() in the global environment
# rather than making a local copy of a() in b()'s execution environment.
environment(a) <<- environment()
a()
}
Test a()
и b()
:
> a()
[1] TRUE
> b()
[1] FALSE
> a()
[1] FALSE
>
Интересно, что это означает, что (обычно временная) среда выполнения b()
сохраняется в памяти даже после завершения b()
, потому что a()
все еще ссылается на среду, поэтому она не может быть собрана сборщиком мусора. Свидетель:
> environment(a)$montePython
[1] "I'm not dead yet!!"