Возможно ли иметь переменную с динамической привязкой в R? Скажем, чтобы работало что-то вроде этого:
f1a <- function() {
x <- 1
f2()
}
f1b <- function() {
x <- 2
f2()
}
f2 <- function() {
f3()
}
f3 <- function() {
# print x
}
f1a() # prints 1
f1b() # prints 2
Я могу явно передать x
вниз по стеку, но это не то, что я ищу. Я спрашиваю о возможности динамической привязки. Я понимаю, что многие люди сказали бы, что передача x
явным образом всегда предпочтительнее, но предположим, что я не могу изменить определение f2
(я могу изменить f1a
, f1b
и f3
). Конечно, у меня может быть глобальная переменная, но я бы предпочел использовать динамическую привязку, если это возможно.
1 ответ
f1a <- function() {
x <- 1
f2()
}
f1b <- function() {
x <- 2
f2()
}
f2 <- function() {
f3()
}
f3 <- function() {
get("x", envir = parent.frame(2))
}
Просто переместите среду, в которой f3
ищет переменную x
.
> f1a()
[1] 1
> f1b()
[1] 2
get("x", envir = parent.frame(2))
ищет переменную с символом x
в среде двумя кадрами вверх по стеку вызовов:
f3 <- function() {
get("x", envir = parent.frame(2))
rlang::trace_back()
}
> f1a()
█
1. └─global::f1a()
2. └─global::f2()
3. └─global::f3()
Если вам нужно перебрать весь стек вызовов до тех пор, пока не встретится первый символ, просто используйте dynGet()
:
f1a <- function() {
x <- 1
f2()
}
f1b <- function() {
x <- 2
f2()
}
f2 <- function() {
f3()
}
f3 <- function() {
f4()
}
f4 <- function() {
f5()
}
f5 <- function() {
dynGet("x")
}
> f1a()
[1] 1
> f1b()
[1] 2
Это остановится при первом обнаруженном x
перемещении вверх по стеку вызовов из вызывающей среды. Итак, если мы настроим f2
:
f2 <- function() {
x <- 3
f3()
}
> f1a()
[1] 3
> f1b()
[1] 3
Опять же, полный стек вызовов можно увидеть с помощью rlang::trace_back
:
f5 <- function() {
dynGet("x")
rlang::trace_back()
}
> f1a()
█
1. └─global::f1a()
2. └─global::f2()
3. └─global::f3()
4. └─global::f4()
5. └─global::f5()
Похожие вопросы
Новые вопросы
r
R — это бесплатный язык программирования с открытым исходным кодом и программная среда для статистических вычислений, биоинформатики, визуализации и общих вычислений. Пожалуйста, используйте минимально воспроизводимые примеры, которые другие могут запустить с помощью копирования и вставки. Показать желаемый результат полностью. Используйте dput() для данных и укажите все небазовые пакеты с помощью library(). Не вставляйте изображения для данных или кода, вместо этого используйте блоки кода с отступом. Для вопросов по статистике используйте https://stats.stackexchange.com.