根据R语言定义, &和&&(相应的|和||)之间的区别是前者是向量化的,而后者不是。
&
&&
|
||
&&和||是所谓的“短路”。这意味着如果第一个操作数足以确定表达式的值,则它们将不计算第二个操作数。
例如,如果&&的第一个操作数为假,则对第二个操作数求值就没有意义了,因为它不能改变表达式的值(false && true和false && false都为假)。当第一个操作数为真时,||也是如此。
false && true
false && false
从该页的表格中,你可以看到&&在VB中等价于AndAlso。NET,我想你指的是。
AndAlso
较短的是向量化的,这意味着它们可以返回一个向量,像这样:
((-2:2) >= 0) & ((-2:2) <= 0) # [1] FALSE FALSE TRUE FALSE FALSE
较长的形式从左到右求值,只检查每个向量的第一个元素,因此上面给出
((-2:2) >= 0) && ((-2:2) <= 0) # [1] FALSE
正如帮助页所说,这使得较长的形式“适合于编程控制流,并且通常在if子句中更受欢迎。”
所以只有当你确定向量的长度为1时你才会使用长形式。
你应该绝对确定你的向量的长度只有1,比如它们是只返回长度为1的布尔值的函数。如果向量的长度可能是>1,你要用简写形式。因此,如果你不是绝对确定,你应该先检查,或者使用简短形式,然后使用all和any将其缩短为长度1,用于控制流语句,如if。
all
any
if
函数all和any通常用于向量化比较的结果,分别检查所有或任何比较是否为真。这些函数的结果肯定是长度为1的,因此适合在if子句中使用,而向量化比较的结果则不适合。(尽管这些结果适合在ifelse中使用。
ifelse
最后一个区别是:&&和||只计算它们需要的所有项(这似乎就是短路的意思)。例如,这里是一个使用未定义值a的比较;如果它没有短路,就像&和|那样,它会给出一个错误。
a
a # Error: object 'a' not found TRUE || a # [1] TRUE FALSE && a # [1] FALSE TRUE | a # Error: object 'a' not found FALSE & a # Error: object 'a' not found
最后,请参见R地狱中名为“andand and”的8.2.17节。
关于“short-circuiting"的答案可能会误导人,但有一些事实(见下文)。在R/S语言中,&&和||只计算第一个参数中的第一个元素。vector或list中的所有其他元素都会被忽略,不管第一个元素的值是多少。这些操作符被设计为与if (cond) {} else{}构造一起工作,并指导程序控制,而不是构造新的向量。&和|操作符被设计用于处理向量,因此它们将“并行”应用,也就是说,沿着最长参数的长度。在进行比较之前,需要对两个向量进行计算。如果向量的长度不相同,则执行较短参数的循环。
if (cond) {} else{}
当&&或||的参数被求值时,存在“短路”;其中,如果从左到右连续的任何值是确定的,则计算停止并返回最终值。
> if( print(1) ) {print(2)} else {print(3)} [1] 1 [1] 2 > if(FALSE && print(1) ) {print(2)} else {print(3)} # `print(1)` not evaluated [1] 3 > if(TRUE && print(1) ) {print(2)} else {print(3)} [1] 1 [1] 2 > if(TRUE && !print(1) ) {print(2)} else {print(3)} [1] 1 [1] 3 > if(FALSE && !print(1) ) {print(2)} else {print(3)} [1] 3
短路的优势只有在论证需要很长时间来评估时才会显现出来。当参数是处理较大对象或具有更复杂的数学操作的函数时,通常会发生这种情况。
更新:news(“R”)的最新版本说,向&&或||提供长度大于1的向量已被弃用,并发出警告,RCore的目的是使其在R的后续版本中成为一个错误。
news(“R”)