Я рекомендую вам прочитать о лексическом определении объема ,
но я думаю, что хороший способ избежать написания большого количества переменных может быть:
get_args_for <- function(fun, env = parent.frame(), inherits = FALSE, ..., dots) {
potential <- names(formals(fun))
if ("..." %in% potential) {
if (missing(dots)) {
# return everything from parent frame
return(as.list(env))
}
else if (!is.list(dots)) {
stop("If provided, 'dots' should be a list.")
}
potential <- setdiff(potential, "...")
}
# get all formal arguments that can be found in parent frame
args <- mget(potential, env, ..., ifnotfound = list(NULL), inherits = inherits)
# remove not found
args <- args[sapply(args, Negate(is.null))]
# return found args and dots
c(args, dots)
}
f_a <- function(b, c = 0, ..., d = 1) {
b <- b + 1
c(b = b, c = c, d = d, ...)
}
f_e <- function() {
b <- 2
c <- 2
arg_list <- get_args_for(f_a, dots = list(5))
do.call(f_a, arg_list)
}
> f_e()
b c d
3 2 1 5
Установка inherits = FALSE
по умолчанию гарантирует, что мы получаем переменные только из указанной среды.
Мы также можем установить dots = NULL
при вызове get_args_for
, чтобы мы не передавали все переменные,
но оставьте многоточие пустым.
Тем не менее, он не совсем устойчив,
потому что dots
просто добавляется в конце,
и если некоторые аргументы не названы,
они могут в конечном итоге соответствовать позиции.
Кроме того, если некоторые значения должны быть NULL
в вызове,
это было бы нелегко обнаружить.
Я бы настоятельно рекомендовал не использовать их ниже в пакете R.
Мало того, что это будет довольно некрасиво,
вы получите кучу заметок из проверки CMD R относительно неопределенных глобальных переменных.
Другие опции.
f_a <- function() {
return(b + c)
}
f_e <- function() {
b <- 2
c <- 2
# replace f_a's enclosing environment with the current evaluation's environment
environment(f_a) <- environment()
d <- f_a()
d
}
> f_e()
[1] 4
Нечто подобное, описанное выше, вероятно, не будет работать внутри пакета R,
так как я думаю, что функции пакета имеют закрытые окружающие среды.
Или:
f_a <- function() {
with(parent.frame(), {
b + c
})
}
f_e <- function() {
b <- 2
c <- 2
f_a()
}
> f_e()
[1] 4
Таким образом, вы не можете навсегда изменить окружение другой функции.
Тем не менее, обе функции будут совместно использовать среду,
так что-то подобное может произойти:
f_a <- function() {
with(parent.frame(), {
b <- b + 1
b + c
})
}
f_e <- function() {
b <- 2
c <- 2
d <- f_a()
c(b,d)
}
> f_e()
[1] 3 5
Где вызов внутренней функции изменяет значения во внешней среде.
Еще один вариант, который немного более гибкий,
поскольку он только временно изменяет окружающую среду, используя eval
.
Тем не менее, есть определенные R-функции, которые обнаруживают свою текущую среду выполнения с помощью "daRk magic",
и не может быть одурачен eval
;
см. это обсуждение .
f_a <- function() {
b <- b + 1
b + c
}
f_e <- function() {
b <- 2
c <- 2
# use current environment as enclosing environment for f_a's evaluation
d <- eval(body(f_a), list(), enclos=environment())
c(b=b, d=d)
}
> f_e()
b d
2 5