R 更换&&;和| |通过我的包中的纯标量操作符?

R 更换&&;和| |通过我的包中的纯标量操作符?,r,packages,R,Packages,作为后续,我想知道在我自己的包中用纯标量运算符替换&&和|是否有任何缺点。它们应该产生与它们的基本对应项完全相同的结果,只是它们在应用于长度大于1的参数时会抛出错误消息。特别是,它们会短路 `&&` <- function(x, y) { if (!x[1]) { stopifnot(length(x) == 1) return(FALSE) } stopifnot(length(x) == 1) if (!y

作为后续,我想知道在我自己的包中用纯标量运算符替换
&&
|
是否有任何缺点。它们应该产生与它们的基本对应项完全相同的结果,只是它们在应用于长度大于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
}

`&&`不。您可以使它对计算机安全,但代码对读者也需要安全。总有一天你会想和别人分享这段代码,或者过了一段时间你自己又会回到这段代码,这种重载会让人困惑。最好使用一个新的函数名

此外,您需要非常小心函数如何处理
NA
NULL
值。您当前版本的行为与
NA
以及
NULL
的常见行为不同;我没有做全面检查。然而,我惊讶地注意到,当其中一个输入为
NULL
时,对于标准的R版本来说,顺序很重要

编辑:关于
NA
值的这个问题需要仔细考虑,这可能是不只是编写一个函数来替换
&&
|
的另一个原因。对于流控制,您需要TRUE或FALSE,NA将抛出一个错误。那么
TRUE&&NA
是否应该抛出错误?或者是
FALSE
?甚至是
真的
?这可能取决于具体情况,执行
if(!is.na(x)&&x)
if(any)(is.na(x))
的常规操作可以为读者提供更大的灵活性和清晰度

如果我继续,我的偏好是将您的新版本视为
all
any
的标量版本,并相应地命名它们,以便像
scalar.all(a,b)
一样使用,而不是
a和&b
。或者,如果您从流量控制的角度考虑,可以添加一个参数来描述如何处理
NA
值,
flowcontrol.all(a、b、NA=c(“错误”、“真”、“假”)

顺便说一句,总的来说,我对你的努力表示赞赏。意识到这些问题并编写安全的代码似乎是一个好主意。但是,在仔细思考并尝试编写我自己的版本之后,我觉得在你自己的包中,最好根据需要逐案执行此操作当您作为一个包编写器知道一个或两个输入只能是标量时,那么这个额外的代码就没有必要了

尽管如此,这里还是尝试了一个
标量.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
}

scalar。我个人不会这么做。你不能只使用不同的函数名?起初我想这样做,但由于运算符优先级的原因遇到了问题。自定义二进制运算符的优先级似乎低于,例如,
==
,这可能会导致典型的
if
条件下出现问题。这当然可以通过addin解决更多的括号,但我不想改变语法。也就是说,如果这真的不破坏任何东西,我实际上更喜欢重载原来的操作符,以确保我真的使用新的到处。(因为我认为它们更安全;也见参考问题。)它们应该影响
globalenv()
中的任何后续表达式,或者最终将沿着当前搜索路径到达该表达式的调用。以这种方式定义的函数称为“掩码”-在加载包时,您应该看到一个警告。代码中没有任何内容会将它们的效果限制为只对包函数有效。如果不希望导出它们,则应研究R名称空间如何工作。
&
&
具有相同的优先级。请阅读
>语法
。如果你定义了
%&&%
,它的优先级会更高。许多人发现这很有用:我不认为你建议创建
%&%
。我只是建议,如果你这样做了,优先级会有问题,并希望给你一个关于R的优先级排序的权威参考。我我不认为像你建议的那样重新定义
&&
| |
会破坏任何依赖于“矢量化”期望的代码。我喜欢这个答案与你之前的答案完全一样。后续问题的后续答案。;-)你知道如何处理我在对这个问题的评论中提到的运算符优先级问题吗?如果真的有必要,我想我可以使用附加的括号,但这让我有点烦。@jihn:如果你重新定义
&&
|
的话,优先级似乎不是问题。如果您不在命令行或.Rprofile中执行此操作,并且不导出它们,那么您将以合理的方式限制影响。编辑答案以反映对
NA
NULL
值的关注,并在包中对其好处进行注释。