在函数中将缺少的参数从函数传递给函数

Mar*_*usN 14 arguments r function-calls

我已经了解到通常的做法是在函数中使用可选参数并使用missing()进行检查(例如,如SO 22024082中所述)

在这个例子中,round0是可选参数(我知道,round0可以定义为逻辑).

foo = function(a, round0) {
    a = a * pi
    if(!missing(round0)) round(a)
    else a
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我从另一个函数调用此函数,我怎么能传递"missing"?

bar = function(b) {
    if(b > 10) round1=T
    foo(b, round1)
}
Run Code Online (Sandbox Code Playgroud)

如果b <10,则bar()中的round1未定义,但无论如何都会传递给foo.如果我修改foo():

foo = function(a, round0) {
    a = a * pi
    print(missing(round0))
    print(round0)
    if(!missing(round0)) round(a)
    else a
}
Run Code Online (Sandbox Code Playgroud)

并运行bar(9)输出为:

bar(9)
[1] FALSE
Error in print(round0) : object 'round1' not found
Called from: print(round0)
Run Code Online (Sandbox Code Playgroud)

这意味着:round0没有丢失,但也无法访问?

我不想在bar()中使用不同的函数调用,如果foo()中有几个可选参数,我将不得不为每个缺失/不丢失编写一个函数调用 - 所有可选参数的组合.

是否可以通过"缺失",或者其他解决方案适用于此问题?

Nic*_*edy 8

在你的例子中,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)
}
Run Code Online (Sandbox Code Playgroud)

或者在参数列表中不能轻易表达默认值的地方:

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)
}
Run Code Online (Sandbox Code Playgroud)

请注意,在这两种情况下,您都需要在调用函数中手动将参数设置为默认值.

foo如果您的if声明中有需要,您也可以在有或没有参数的情况下调用您的函数:

bar = function(b) {
    if (b > 10) foo(b, TRUE) else foo(b)
}
Run Code Online (Sandbox Code Playgroud)

但是你不能(据我所知)创建一个变量,missing而不是仅仅将它作为参数传递.


Cla*_*lke 7

最近遇到了类似的问题,想大体解决一下。我认为可以按照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())
}
Run Code Online (Sandbox Code Playgroud)

以下是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
Run Code Online (Sandbox Code Playgroud)

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())
}
Run Code Online (Sandbox Code Playgroud)

以下是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
Run Code Online (Sandbox Code Playgroud)

有关的其他信息,请参阅此答案do.call()