Как проверить наличие входного аргумента для функций R - PullRequest
33 голосов
/ 26 марта 2012

У меня есть функция, определенная как

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"), и ни один из них не работает.

Ответы [ 4 ]

59 голосов
/ 28 марта 2012

Я думаю, вы просто ищете hasArg

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

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

From ?hasArg:

Выражение hasArg (x), например, похоже на! отсутствует (x), с двумя исключениями.Во-первых, hasArg будет искать аргумент с именем x в вызове, если x не является формальным аргументом для вызывающей функции, но ... is.Во-вторых, hasArg никогда не генерирует ошибку, если ему дано имя в качестве аргумента, тогда как отсутствие (x) генерирует ошибку, если x не является формальным аргументом.

30 голосов
/ 26 марта 2012

@ У 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
8 голосов
/ 27 марта 2012

Могут быть случаи, когда вы не захотите вызывать 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
4 голосов
/ 26 марта 2012

Вот способ, которым я часто делаю это. Сначала преобразуйте ... в список, затем проверьте, не являются ли элементы NULL:

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

Некоторые результаты:

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