如何检查R函数的输入参数是否存在

53

我有一个被定义为

myFun <- function(x, y, ...) {
  # using exists
  if (exists("z")) { print("exists z!") }
  # using missing
  try(if (!missing("z")) { print("z is not missing!") }, silent = TRUE)
  # using get
  try(if (get("z")) { print("get z!") }, silent = TRUE)

  # anotherFun(...)
}
在这个函数中,我想要检查用户是否在参数列表中输入了“z”。我该如何做?我尝试过exists("z")missing("z")get("z"),但都没有起作用。

我想要在函数中检查参数列表是否包含用户输入的"z",请问应该如何实现?我已经尝试了exists("z")missing("z")get("z"),但是它们都不起作用。


1
你能准确展示一下你是怎么使用 missing 的吗?因为据我所知,那是要用的正确函数。 - joran
如果您提供更多的上下文信息,会更有帮助。也许有更好的方法来实现您想要完成的任务。 - Joshua Ulrich
1
@joran,missing()仅适用于参数。这里没有参数z,它只能作为...的一部分输入。 - Sacha Epskamp
@SachaEpskamp 我同意。我只是不确定 OP 写的是否是他们实际在做的事情。 - joran
我已经修改了问题中的代码,使其更易于理解。感谢您的评论。 - danioyuan
4个回答

83

我认为你只是在寻找hasArg

myFun <- function(x, y, ...) { 
  hasArg(z)
}

> myFun(x=3, z=NULL)
[1] TRUE

来自 ?hasArg:

例如,表达式hasArg(x)类似于!missing(x),但有两个例外。首先,如果x不是调用函数的形式参数之一,hasArg将在调用中查找名为x的参数。其次,如果给定名称作为参数,hasArg永远不会生成错误,而missing(x)会在x不是形式参数时生成错误。


34

@Sacha Epskamp提供了一个相当不错的解决方案,但它并不总是有效。如果将“z”参数传递为NULL,则会失败...

# Sacha's solution
myFun <- function(x, y, ...) { 
  args <- list(...)
  exist <- !is.null(args[['z']])
  return(exist)
}

myFun(x=3, z=NULL) # FALSE, but should be TRUE!


# My variant
myFun2 <- function(x, y, ...) {
  args <- list(...)
  exist <- "z" %in% names(args)
  exist
}

myFun2(x=3, z=NULL) # TRUE

10

有时候你可能不希望调用list(...),因为这会评估点中所有表达式的结果。例如,

myFun <- function(x, y, ...){
  myArgs <- list(...)
  zInArgs <- ("z" %in% names(myArgs))
  return(zInArgs)
}

myFun(x = 2, y = "Happy", z = list(rep(rnorm(2e6), 100)))

这会花费很长时间。相反,使用match.call()

myFun <- function(x, y, ...){
  myArgs <- match.call()
  zInArgs <- ("z" %in% names(myArgs))
  return(zInArgs)
}

myFun(x = 2, y = "Happy", z = list(rep(rnorm(2e6), 100)))
第一个例子在我的电脑上仍在运行,而第二个例子几乎不需要时间。
编辑:回答@CarlWitthoft的评论:
R> system.time(
+   (myAns <- myFun(x = 2, y = "Happy", z = list(rep(rnorm(2e6), 100))))
+ )
   user  system elapsed 
      0       0       0 
R> myAns
[1] TRUE

为了完整起见,您能否报告第二个示例运行所需的时间? - Carl Witthoft
嗨@CarlWitthoft,请查看我上面的编辑。你得到了不同的结果吗? - BenBarnes
1
很遗憾,由于我目前还不能在工作中安装R,所以我的结果是NULL。非常感谢您进行时间测试。 - Carl Witthoft

5

以下是我常用的方法。首先将 ... 转换为列表,然后检查元素是否不为 NULL

myFun <- function(x, y, ...) { 
args <- list(...)
exist <- !is.null(args[['z']])
return(exist)
}

一些结果:

> myFun()
[1] FALSE
> myFun(z=1)
[1] TRUE

我认为这不是 ... 应该被使用的预期方式。 这更像是将参数传递给另一个函数的方式,但这也是我目前在我的包中使用它的方式(我真的应该改变它:)) - Sacha Epskamp
1
Sacha,我同意你的观点。如果在这个函数中使用了“z”,它就不应该出现在...但很多时候代码已经编写好了,对参数列表进行一次更改可能会引入错误,需要进行许多更改才能修复。所以这是我的懒惰方式来使它工作。 :) - danioyuan
1
我添加了一个替代方案,也可以处理 myFun(z=NULL) - Tommy
@danioyuan,这还可以为您提供令人惊叹的隐藏和未记录的参数,只有您知道! - Sacha Epskamp
@danioyuan:添加参数的安全且可能是“正确”的方法是将其放在列表的最后,并分配默认值,即myfunc(x,y,...)变成myfunc(x,y,z=1,...)。据我所知,这将提供完整的向后兼容性。 - Carl Witthoft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接