是的,我知道,有关R中&
与&&
的使用情况的问题(例如,请参阅this one),但我没有找到一个问题这特别回答了我的问题。
据我了解差异,
&
进行逐元素的矢量化比较,就像其他算术运算一样。因此,它返回长度> 1的逻辑矢量。如果两个参数都具有长度> 1,则为1; 1。&&
比较两个向量的第一个元素,并始终返回长度为1的结果。此外,它短路:cond1 && cond2 && cond3 && ...
仅评估{{1}如果cond2
是cond1
,等等。这允许TRUE
之类的内容,特别是在某些情况下使用if(exists("is.R") && is.function(is.R) && is.R())
是绝对必要的。此外,&&
发出警告
条件的长度> 1,只使用第一个元素
如果其条件有多个元素。
从这些预赛判断来看,我认为在不需要短路的所有if
声明中更倾向于&
到&&
更安全。
如果在计算过程中出现问题,我意外地在if
的一个参数中有一个向量,我会收到警告,这很好。如果没有,一切都很好。
另一方面,如果我使用&
,并且在我的计算中出现了问题,并且&&
的一个参数是向量,我不会收到警告。这是不好的。如果出于某种原因,我真的想比较两个向量的第一个元素,我认为明确而不是隐含地这样做会更清晰。
请注意,这与R程序员之间的共同协议相反,与R docs推荐的内容相反。 (1)
因此我的问题:除了短路之外是否有任何理由使&&
优于&&
&
语句中的if
?
(1)引用help(&&)
:
'&安培;'和'&&'表示逻辑AND和'|'和'||'表明 逻辑或。较短的形式执行元素比较 与算术运算符的方式大致相同。更长的形式 从左到右评估只检查每个元素的第一个元素 向量。评估仅在确定结果之前进行。 较长的形式适用于编程控制流程和 通常在'if'子句中首选。
答案 0 :(得分:5)
否,使用&&
除了短路之外没有任何其他优势。
然而,对于控制流程来说,短路是非常可取的,因此它应该是默认值。 if
语句不应该采用向量化的参数 - 这就是ifelse
的用途。如果您将逻辑向量传递到if
,通常会使用any
或all
将其合并为单个逻辑值进行评估。
短路的主要优点是避免冗长或容易出错的步骤(例如互联网连接 - 尽管这些应通过try
处理):
#avoiding lengthy calculations
system.time(if(FALSE & {Sys.sleep(2);TRUE}) print("Hello"))
user system elapsed
0.00 0.00 1.99
system.time(if(FALSE && {Sys.sleep(2);TRUE}) print("Hello"))
user system elapsed
0 0 0
#avoiding errors
if(FALSE & {stop("Connection Failed");TRUE}) print("Success") else print("Condition not met")
Error: Connection Failed
if(FALSE && {stop("Connection Failed");TRUE}) print("Success") else print("Condition not met")
[1] "Condition not met"
很明显,为了利用这些功能,您必须事先知道哪些步骤花费的时间最长或容易出错,并适当地构建逻辑语句。
答案 1 :(得分:5)
简答:是的,不同的符号使读者的意思更加明确。
感谢这个有趣的问题!如果我可以总结一下,对于您所关联的问题,my answer的这一部分似乎是一个具体的后续行动,
...只有在确定时,才想使用长格式 向量是长度一。你应该绝对肯定你的向量 只有长度为1,例如在它们是函数的情况下 只返回长度为1的布尔值。你想要使用短格式 向量的长度可能> 1。所以,如果你不完全确定,那么你 应首先检查,或使用简短形式,然后使用全部和 任何将它减少到长度1用于控制流程语句, 喜欢如果。
我以这种方式听到你的问题(给出评论):但如果输入是长度为1,&
和&&
会做同样的事情,所以除了短路之外,为什么更喜欢&&
?也许&
可能是首选,因为如果它们不是长度为1,if
会给我一个警告,帮助我更加确定输入是长度为一。
首先,我同意@James的评论,你可能会夸大警告的价值&#34 ;;如果它不是长度1,那么更安全的事情就是妥善处理这个问题,而不仅仅是向前耕作。如果&&
不是一个长度,那么你可以提出&&
应该抛出错误的情况,也许是一个好例子;我不知道它为什么会这样做。但是,如果不及时回过头来,我们现在能做的最好的事情就是检查输入确实适合您的使用。
鉴于此,您已经检查以确保您的输入是合适的,我仍然会建议<-
因为它在语义上提醒我作为读者我应该确保输入是标量(长度为1)。我过去常常想到这个提醒对我有帮助。它遵循以下原则:不同的操作应该有不同的符号,对我来说,一个用于标量的操作与矢量化操作不同,它保证了一个不同的符号。
(不要开始一场火焰战(我希望),但这也是我更喜欢=
到var yourWindow = window.open('http://google.com');
的原因;一个用于分配变量,一个用于将参数设置为函数。虽然这很深同样的事情,它在实践中的不同之处在于使不同的符号对我作为读者有用。)