all.equal,带有列表和引号(expr =)

时间:2016-04-21 05:25:56

标签: r

前段时间我创建了一个函数,用于检查参数是否缺失,如果是,则返回信息性错误。它看起来像这样:

#' Check if arguments are missing and raise error if they are
#'
#' Checks if arguments are missing and raises an error if they are. Put this in the beginning of your functions to check the input and give useful errors without writing checking code over and over again.
#' @param var_names (chr vector) Names of variables to check.
#' @param error_msg (chr scalar) A template of the error message to show.
#' @export
#' @examples
#' test_func = function(y) {
#' check_missing("y")
#' T
#' }
#' test_func(y = ) #throws error
#' test_func(y = 1) #returns true
check_missing = function(var_names, error_msg = "[VAR] was missing! Please supply the input and try again.") {

  #parent.frame as list
  pf = as.list(parent.frame())

  #check each if missing
  for (name in var_names) {
    #is it there at all?
    if (!name %in% names(pf)) {
      stop(name + " is not even found in the parent.frame! Check the variable names.", call. = F)
    }

    #check if missing
    if (are_equal(pf[[name]], quote(expr = ))) {
      stop(str_replace(error_msg, pattern = "\\[VAR\\]", name), call. = F)
    }
  }

  #all fine
  return(invisible(NULL))
}

来自this package的功能,用于:

library(devtools);install_github("deleetdk/kirkegaard");library("kirkegaard")

在一个特定的用例中,我得到一个列表作为传递给上面检查函数的参数。但是,这导致:

Error in all.equal.list(target, current, ...) : 
  argument "current" is missing, with no default

可以用这个最小的例子重现这一点:

> all.equal(list(), quote(expr = ))
Error in all.equal.list(list(), quote(expr = )) : 
  argument "current" is missing, with no default

base-r函数中是否存在错误,或者我误解了某些内容?

我通过插入以下内容来解决问题:

if (is.list(pf[[name]])) return(invisible(NULL)) #evade bug?

在违规行之前(对are_equal的调用,all.equal的包装。)

1 个答案:

答案 0 :(得分:1)

如果使用identical代替,问题应该会消失 all.equal

首先,请注意quote(expr = )会创建一个丢失的对象:

test_env <- new.env()
test_env$a <- quote(expr = )

ls.str(test_env)
a : <missing>

接下来,请注意all.equal在两个参数都正常工作 缺少,但只有其中一个缺失时失败。

all.equal(target = quote(expr = ), current = test_env$a)
[1] TRUE

all.equal(target = list(), current = test_env$a)
Error in all.equal.list(target = list(), current = test_env$a) : 
  argument "current" is missing, with no default  

原因是all.equal首先检查参数 是相同的 - 如果没有,它会尝试做更多的事情 比较(详见?all.equal)。

如果使用identical代替,则不存在此问题 all.equal

identical(x = quote(expr = ), y = test_env$a)
[1] TRUE

identical(x = list(), y = test_env$a)
[1] FALSE

基于此,我猜你的代码应该可以替换 (are_equal(pf[[name]], quote(expr = ))) (identical(pf[[name]], quote(expr = )))