Scope - как оценивать объект в родительской среде, если существует локальный var с тем же именем?
Если у меня есть две вложенные среды, использующие одно и то же имя переменной, как бы я захватил значение внешней среды?
Мне трудно понять, как правильно это реализовать. Я попробовал несколько вариантов parent.frame(x)
и sys.frame(x)
внутри eval. Мы ценим любые предложения.
ПРИМЕР:
outerFunc <- function() {
obj <- "Outer Object"
innerFunc()
}
innerFunc <- function() {
# A local variable with same name is created
obj <- "Inner Object"
# would like to grab the value of obj from the outer environment
obj.callingFunc <- eval(obj, envir=sys.frame(-1))
cat(obj.callingFunc) # gives "Inner Object" instead of "Outer Object"
}
> outerFunc()
Inner Object
Очевидные решения (Pass obj
явно. Использовать другое имя переменной и т.д.) не доступны мне в этом конкретном случае.
ИЗМЕНИТЬ
изучение ответов @GregSnow и @Dwin ниже
# THESE WORK
eval(quote(obj), envir=parent.frame()) # equivalent to evalq(obj, envir=parent.frame())
get("obj", envir=parent.frame())
# THESE DO *NOT* WORK
eval("obj", envir=parent.frame())
get(quote(obj), envir=parent.frame())
Любые мысли о влиянии цитирования в get()
vs eval()
?
Ответы
Ответ 1
outerFunc <- function() {
obj <- "Outer Object"
innerFunc()
}
innerFunc <- function() {
# A local variable with same name is created
obj <- "Inner Object"
# would like to grab the value of obj from the outer environment
cat( get('obj', envir=parent.frame()) )
}
outerFunc()
#Outer Object
Может также использоваться: eval(quote(obj), envir=sys.frame(-1))
. Становится ясно, что значение quote (expr) отличается от значения "expr". Функция get
"ожидает" (или, возможно, более точно спроектирована) для получения символьных значений, тогда как eval
ожидает вызовы и выражения, т.е. "Языковые" объекты. Существует некоторая полупроницаемая мембрана между данными и языком в R и get
является одним из мембранных каналов, через которые вы можете передавать объекты с символами в языковой домен.
Ответ 2
Измените eval
на evalq
или иначе укажите obj
в вызове eval. Как и obj оценивается до того, как ему будет присвоено значение eval
, поэтому оно имеет внутреннее значение, цитируя его, передайте выражение (а не значение) на eval
для оценки.