在R中从函数到函数传递缺少的参数

在R中从函数到函数传递缺少的参数,r,arguments,function-calls,R,Arguments,Function Calls,我了解到在函数中使用可选参数并用missing()检查它们是一种常见的做法 (如中所述) 在本例中,round0是可选参数(我知道,round0可以定义为逻辑) 但是如果我从另一个函数调用这个函数,我如何传递“missing”呢 bar = function(b) { if(b > 10) round1=T foo(b, round1) } 如果b

我了解到在函数中使用可选参数并用missing()检查它们是一种常见的做法 (如中所述)

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

但是如果我从另一个函数调用这个函数,我如何传递“missing”呢

bar = function(b) {
    if(b > 10) round1=T
    foo(b, round1)
}
如果b<10,则未定义bar()中的round1,但仍将传递给foo。如果我修改foo():

和运行条(9),输出为:

bar(9)
[1] FALSE
Error in print(round0) : object 'round1' not found
Called from: print(round0)
这意味着:round0没有丢失,但也无法访问

我不想在bar()中使用不同的函数调用,如果foo()中有多个可选参数,我必须为每个缺失/未缺失(所有可选参数的组合)编写一个函数调用


是否可以传递“缺失”,或者有什么其他解决方案适用于此问题?

在您的示例中,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)
}

@moody_mudskipper's展示了一种显示如何生成缺失值的替代方法。

我最近遇到了一个类似的问题,希望以一种通用的方式解决它。我认为可以按照下面函数
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())
}
如果不想将所有参数交给下一个函数或添加一些参数,可以在
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())
}

有关
do.call()
的更多信息,请参阅。您可以使用
substitute()
无参数创建缺少的对象

在您的情况下,我们可以使
round1
成为
else
子句中缺少的对象:

foo=函数(a,round0){
a=a*pi
如果(!缺少(第0轮))轮(a)
其他a
}
bar=功能(b){
如果(b>10)轮1=T,则轮1[1]28.27433

由(v0.3.0)于2019-10-24创建的

rlang
还提供了一个函数
missing_arg()
,该函数使参数丢失

foo=函数(a,round0){
a=a*pi
如果(!缺少(第0轮))轮(a)
其他a
}
bar=功能(b){
如果(b>10)第1轮[1]28.27433

由(v0.3.0)创建于2020-12-02通常,如果您以特定形式调用函数,您应该确保您拥有所有参数。在这里,我将在
bar
的开头添加
round1=F
,并使用
if(!missing(round0)&&round0)
更新
foo
。missing允许您调用
foo(a)
foo(a,T/F)
,如果您使用两个参数调用它,则第二个参数不会丢失并且必须是可解析的。我的猜测是,
missing
在表示函数参数的promise对象具有非空表达式槽时返回
FALSE
。添加行
print(substitute(round0))
在修改后的
foo
函数中的
a=a*pi
之后,执行
foo(9)
substitute
将提取表达式槽。它将不打印任何内容,即
round0
的空表达式槽。现在尝试
bar(9)
。这将打印
round1
。但是当您使用
print
时,R将尝试计算尚未定义的
round1
(惰性计算)。
missing()
需要将其输入为某个内容(其名称在这方面是一个矛盾修饰法)。这是一个空表达式,它似乎是
substitute()
可以创建一些,你也可以做
alist(x=)[[1]]
。为了得到详细的答案,我们需要进入C实现,我对它不太了解。最后一条语句不准确。你可以通过将变量定义为
quote(expr=)
substitute()
alist(x=1)[1]来丢失一个变量
。前者是最有效的。{rlang}有一个
missing_arg
函数也有同样的功能。请看下面我自己的答案。@Moody_mudscappper谢谢,我不知道。我修改了我的答案,指向你的答案。
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)
}
bar = function(b) {
    if (b > 10) foo(b, TRUE) else foo(b)
}
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()
[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
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()
[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