Функция base::substitute(expr, env)
, согласно странице документации,
возвращает дерево синтаксического анализа для (неоцененного) выражения expr, заменяя любые переменные, связанные в env.
Я ищу способ замены любых переменных, привязанных не к одной конкретной среде, а ко всем средам в текущем стеке вызовов, т. е. ко всем средам, встречающимся при переборе parent.frame(i)
, где i
находится в seq_len(sys.nframe())
. Кроме того, я хотел бы, чтобы применялись стандартные правила области действия.
Это противоречие: стандартная область видимости в R является лексической, но то, что я описываю здесь, является динамической областью видимости (спасибо @MikkoMarttila за помощь в прояснении этого). Что мне действительно нужно, так это способ замены любых переменных, связанных не в одной конкретной среде, а во всех родительских включающих средах, набор которых можно перечислить, многократно применяя base::parent.env()
.
Рассмотрим следующий пример:
do_something <- function(todo) {
cat(
paste(
deparse(substitute(todo, environment())),
collapse = "\n"
)
)
}
nested_do <- function() {
var_2 <- "goodbye"
do_something({
print(var_1)
print("world")
print(var_2)
})
}
var_1 <- "hello"
nested_do()
В настоящее время это дает
print(var_1)
print("world")
print(var_2)
где я хотел бы иметь
print("hello")
print("world")
print("goodbye")
Я просмотрел base::bquote()
и rlang::enexpr()
, но для обоих я должен явно пометить переменные для замены/отключения кавычек с помощью .()
или !!
. Я бы предпочел не указывать переменные вручную, а разрешать все найденное (как в base::substitute()
). Кроме того, я попытался итеративно применить base::substitute()
с соответствующими аргументами env
, и я посмотрел на oshka::expand()
, но ничего из того, что я пробовал, не делает то, что мне нужно.
Любая помощь очень ценится.
Дополнительный контекст
Я пытаюсь добиться следующего: я работаю над кластером, на котором работает LSF. Это означает, что я могу отправлять задания с помощью инструмента отправки bsub
, который может принимать R-файл в качестве входных данных. Теперь я хотел бы иметь скрипт, который генерирует эти входные файлы (например, с помощью функции do_something()
).
long_running_fun <- function(x) {
Sys.sleep(100)
x / 2
}
var_1 <- 2 + 2
var_2 <- var_1 + 10
do_something({
print(var_1)
var_3 <- long_running_fun(var_2)
print(var_3)
})
Я в приведенном выше случае хочу, чтобы следующее (или что-то эквивалентное) было записано в файл
print(4)
var_3 <- long_running_fun(14)
print(var_3)