更换&& amp;是否安全和||在我的包中通过纯粹的标量运算符?

时间:2015-04-28 23:38:16

标签: r packages

作为my previous question on the usage of && and || in if statements的后续行动,我想知道在我自己的软件包中用纯标量运算符替换&&||是否有任何缺点。这些应该产生与它们的基本对应物完全相同的结果,除了它们在应用于长度> 1的参数时抛出错误消息。特别是,它们会短路。

`&&` <- function(x, y) {
    if (!x[1]) {
        stopifnot(length(x) == 1)
        return(FALSE)
    }
    stopifnot(length(x) == 1)
    if (!y[1]) {
        stopifnot(length(y) == 1)
        return(FALSE)
    }
    stopifnot(length(y) == 1)
    TRUE
}

`||` <- function(x, y) {
    if (x[1]) {
        stopifnot(length(x) == 1)
        return(TRUE)
    }
    stopifnot(length(x) == 1)
    if (y[1]) {
        stopifnot(length(y) == 1)
        return(TRUE)
    }
    stopifnot(length(y) == 1)
    FALSE
}

在包装中进行这些替换是否安全?或者可能会破坏某些东西? (除了实际依赖于矢量化行为的函数,显然......)

请注意,我不打算导出这些功能;它们仅供我内包装使用。

如果我理解正确,那么这些替换只会影响我自己的功能。它们不会影响我的包裹以外的任何东西,对吧?

1 个答案:

答案 0 :(得分:1)

没有。您可能能够使计算机安全,但代码也需要对读者安全。有一天你会想和别人分享这个代码,或者你会在一段时间后自己回来,这种超载会让人感到困惑。到目前为止,最好使用新的函数名称。

此外,您需要非常小心处理您的函数如何处理NANULL值。您当前版本的行为与NA的常规版本不同,可能与NULL不同;我没有做全面检查。但我很惊讶地注意到,当其中一个输入为NULL时,订单对标准R版本很重要。

编辑:NA值的这个问题值得思考,可能还有另一个原因,就是不要只编写一个旨在取代&&||的函数。对于流控制,您需要TRUE或FALSE,NA将抛出错误。那么TRUE && NA会抛出错误吗?或者FALSE?甚至是TRUE?这可能取决于if(!is.na(x) && x)if(any(is.na(x)))的常见事情可能为读者提供更多的灵活性和清晰度。

如果我要继续,我的偏好是将您的新版本视为allany的标量版本并相应地命名,以便像scalar.all(a, b)一样使用a && b。或者,如果您从流量控制角度考虑它,可以添加一个参数来描述如何处理NA值,flowcontrol.all(a, b, na=c("error", "TRUE", "FALSE")

顺便说一下,我赞赏你的努力。意识到这些问题并编写代码以保证它们的安全性似乎是一个好主意。然而,在考虑了这一点并尝试简要地编写我自己的版本之后,我觉得在你自己的软件包中,最好根据需要逐个进行。有时您会知道作为包编写器的一个或两个输入只能是标量,然后这个额外的代码是不必要的。

但是,这是scalar.all函数的尝试。

scalar.all <- function(...) {
   ns <- eval(substitute(alist(...)))
   sofar <- TRUE
   for(n in ns) {
      x <- eval(n)
      if (length(x) != 1L) {
        stop(paste(list(n)), " is not a scalar with length 1")
      }
      if (is.na(x)) sofar <- NA
      else if (!x) return(FALSE)
   }
   sofar
}