Передача отсутствующего аргумента от функции к функции в R
Я узнал, что обычной практикой является использование необязательных аргументов в функции и проверка их с помощью missing () (например, как обсуждалось в SO 22024082)
В этом примере round0 является необязательным аргументом (я знаю, round0 может быть определен как логический).
foo = function(a, round0) {
a = a * pi
if(!missing(round0)) round(a)
else a
}
Но что, если я вызываю эту функцию из другой функции, как я могу передать слово "отсутствует"?
bar = function(b) {
if(b > 10) round1=T
foo(b, round1)
}
Если b < 10, то round1 в bar () не определен, но все равно передается в foo. Если я изменю foo ():
foo = function(a, round0) {
a = a * pi
print(missing(round0))
print(round0)
if(!missing(round0)) round(a)
else a
}
и запустите бар (9):
bar(9)
[1] FALSE
Error in print(round0) : object 'round1' not found
Called from: print(round0)
Это означает, что round0 не пропущен, но также недоступен?
Я не хочу использовать разные вызовы функций в bar (), если в foo () есть несколько необязательных аргументов, мне придется написать вызов функции для каждого отсутствующего / не пропущенного - комбинации всех необязательных аргументов.
Можно ли пропустить "отсутствует", или какое другое решение подойдет для этой проблемы?
2 ответа
В вашем примере round0 не пропущен, он установлен в round1
который не определен (в отличие от отсутствия).
В общем, лучший способ сделать это - использовать значение по умолчанию, в вашем случае FALSE
:
foo = function(a, round0 = FALSE) {
a = a * pi
if (!round0) round(a)
else a
}
bar = function(b) {
round1 <- FALSE
if (b > 10) round1=TRUE
foo(b, round1)
}
или где значение по умолчанию не может быть легко выражено в списке параметров:
foo = function(a, round0 = NULL) {
a = a * pi
if(!is.null(round0)) round(a)
else a
}
bar = function(b) {
round1 <- NULL
if (b > 10) round1=TRUE
foo(b, round1)
}
Обратите внимание, что в обоих случаях вам нужно вручную установить параметр в качестве значения по умолчанию в вызывающей функции.
Вы также можете позвонить foo
функция с или без аргумента, если это необходимо в вашем if
заявление:
bar = function(b) {
if (b > 10) foo(b, TRUE) else foo(b)
}
Но вы не можете (насколько я знаю) сделать переменную missing
кроме просто не передавая это в качестве аргумента.
Недавно я столкнулся с подобной проблемой и хотел решить ее в общем виде. Я думаю, что это можно сделать, как показано в определении функции g()
ниже:
f <- function(a = 5, b = 3, c = 2, d = 7) {
if (missing(a)) {print("a is missing.")}
if (missing(b)) {print("b is missing.")}
if (missing(c)) {print("c is missing.")}
if (missing(d)) {print("d is missing.")}
cat(a, b, c, d)
}
g <- function(a = 1, b = 1, c = 1, d = 1) {
args <- as.list(match.call())
args[[1]] <- NULL # remove first list element, it's the function call
do.call(f, args, envir = parent.frame())
}
Вот что мы получаем при звонке g()
с разными наборами аргументов:
> g()
[1] "a is missing."
[1] "b is missing."
[1] "c is missing."
[1] "d is missing."
5 3 2 7
> g(a = 3)
[1] "b is missing."
[1] "c is missing."
[1] "d is missing."
3 3 2 7
> g(b = 10, c = 10)
[1] "a is missing."
[1] "d is missing."
5 10 10 7
Вы можете добавить или удалить из args
список, если вы не хотите передавать все аргументы следующей функции или хотите добавить некоторые. В качестве примера см. Следующую функцию g()
это делает это в общем виде:
g <- function(a = 1, b = 1, c = 1, x = 1, y = 1, z = 1) {
f_args <- c("a", "b", "c") # arguments we want to hand off to function f
# obtain the list of arguments provided
args <- as.list(match.call())
# remove first list element, it's the function call
args[[1]] <- NULL
# remove the arguments that are not listed in f_args
args <- args[na.omit(match(f_args, names(args)))]
# now add argument d, we always want it to be 0:
args <- c(args, list(d = 0))
do.call(f, args, envir = parent.frame())
}
Вот что мы получаем при звонке g()
с разными наборами аргументов:
> g()
[1] "a is missing."
[1] "b is missing."
[1] "c is missing."
5 3 2 0
> g(a = 3)
[1] "b is missing."
[1] "c is missing."
3 3 2 0
> g(b = 10, c = 10)
[1] "a is missing."
5 10 10 0
Смотрите этот ответ для получения дополнительной информации о do.call()
,
Вы можете создать недостающий объект, используя substitute()
без аргументов.
В вашем случае мы могли бы сделать round1
отсутствующий объект в else
пункт:
foo = function(a, round0) {
a = a * pi
if(!missing(round0)) round(a)
else a
}
bar = function(b) {
if(b > 10) round1=T else round1 <- substitute()
foo(b, round1)
}
bar(9)
#> [1] 28.27433
Создано 24.10.2019 пакетом REPEX (v0.3.0)
rlang
предоставляет также функцию
missing_arg()
это делает аргумент отсутствующим.
foo = function(a, round0) {
a = a * pi
if(!missing(round0)) round(a)
else a
}
bar = function(b) {
if(b > 10) round1 <- TRUE else round1 <- rlang::missing_arg()
foo(b, round1)
}
foo(9)
#> [1] 28.27433
bar(9)
#> [1] 28.27433
Создано 02.12.2020 пакетом REPEX (v0.3.0)