In R, there is the more general &
and |
that applies over a vector.
If you use &&
or ||
, you will be exposed to bugs. So I can't think of a reason why we would use either of these.
In R, there is the more general &
and |
that applies over a vector.
If you use &&
or ||
, you will be exposed to bugs. So I can't think of a reason why we would use either of these.
I feel like this is implicitly covered by Boolean operators && and || , but:
A && B
, B
is only evaluated if it needs to be; if A
is FALSE
then we know the result will be FALSE
without evaluating B
B
would throw an error if A
is FALSE
(if we wanted to do this with &
we would have to include some kind of try()
/tryCatch()
to handle that case)I agree that the evaluation rule that &&
/||
evaluate[s] left to right examining only the first element of each vector
(without even throwing a warning)
seems odd and prone to produce unwanted/surprising results, i.e. if you accidentally use a vector of length>1 as part of a control statement. It would seem more natural to throw a warning or error in this case (e.g., the way that if()
does if you give it a vector of length>1).
According to this tweet
It's a design bug in R; should really give error. There's work since R 3.6.0 (2019) to fix it. Until fixed, set
_R_CHECK_LENGTH_1_LOGIC2_=true
in your~/.Renviron
to get "Error in c(TRUE, TRUE) && c(TRUE, TRUE) : 'length(x) = 2 > 1' in coercion to 'logical(1)'"
(See this commit from 2018; this flag is used in CRAN checks.)
I don't know whether there is an (to me) obscure use case where this is convenient, or if it's for S compatibility. From Becker et al. 1988 The New S Language (via Google Books):
Frustratingly, this does not explicitly define what happens if either cond1
or cond2
has length > 1 ...
The longer forms are intended for control statements where only a single logical value is allowed (even though more then one value is accepted with a warning). However, the longer forms only evaluate until the result is clear. Consider the following.
TRUE || FALSE
In this case, the FALSE
does not have to be considered because the result is already clear from the TRUE
. Consequently, the FALSE
is not even evaluated. This is particularly useful if your second condition relies on the first condition being true because it would throw an error otherwise.
x <- "a"
if (is.numeric(x) & x/2 > 5) print(x)
if (is.numeric(x) && x/2 > 5) print(x)
The first case throws an error because you can't divide a character by a number. The second case will do just fine.