324

According to the R language definition, the difference between & and && (correspondingly | and ||) is that the former is vectorized while the latter is not.

According to the help text, I read the difference akin to the difference between an "And" and "AndAlso" (correspondingly "Or" and "OrElse")... Meaning: That not all evaluations if they don't have to be (i.e. A or B or C is always true if A is true, so stop evaluating if A is true)

Could someone shed light here? Also, is there an AndAlso and OrElse in R?

mattb
  • 2,787
  • 2
  • 6
  • 20
Suraj
  • 35,905
  • 47
  • 139
  • 250
  • Also see similar questions at http://stackoverflow.com/q/6933598/210673 and http://stackoverflow.com/q/7953833/210673 (now closed as a duplicate). – Aaron left Stack Overflow Oct 22 '12 at 14:27
  • 3
    I think && and || are badly implemented in R. In other languages they the conditional AND and OR operators, they perform a logical AND or OR boolean operations, but only evaluate its second operand if necessary. In R don't do anything useful. – skan Nov 28 '16 at 18:51
  • 2
    @skan: I think your claim that `&&` and `||` behaves differently than unspecified "other languages" which do not evaluate a second argument when the first is determinate is simply FALSE. – IRTFM Feb 12 '21 at 22:01
  • @IRTFM Your assertion is FALSE and rude. For example in Julia: https://docs.julialang.org/en/v1/manual/control-flow/#Short-Circuit-Evaluation "they don't necessarily evaluate their second argument" "only the minimum number of expressions are evaluated as are necessary to determine the final boolean value of the entire chain" "In the expression a && b, the subexpression b is only evaluated if a evaluates to true." – skan Apr 20 '22 at 16:45
  • 3
    I’m R the second argument of && is not evaluated if the first is FALSE. So no difference from Julia in that respect. – IRTFM Apr 21 '22 at 13:41
  • @skan You might want to delete that old comment of yours since it's wrong (as I hope you'll agree by now) and has the potential of misleading cursory readers. – Konrad Rudolph Feb 14 '23 at 13:28

5 Answers5

434

The shorter ones are vectorized, meaning they can return a vector, like this:

((-2:2) >= 0) & ((-2:2) <= 0)
# [1] FALSE FALSE  TRUE FALSE FALSE

The longer form is not, and so (as of 4.3.0) must be given inputs of length 1. (Hooray! Less checking necessary, see below.)

Until R 4.3.0, giving && inputs of length > 1 did not throw an error, but instead evaluated left to right examining only the first element of each vector, so the above gave:

((-2:2) >= 0) && ((-2:2) <= 0)
# [1] FALSE

As the help page says, this makes the longer form "appropriate for programming control-flow and [is] typically preferred in if clauses."

So you want to use the long forms only when you are certain the vectors are length one, and as of 4.3.0, R enforces this.

If you're using a previous version, you should be absolutely certain your vectors are only length 1, such as in cases where they are functions that return only length 1 booleans. You want to use the short forms if the vectors are length possibly >1. So if you're not absolutely sure, you should either check first, or use the short form and then use all and any to reduce it to length one for use in control flow statements, like if.

The functions all and any are often used on the result of a vectorized comparison to see if all or any of the comparisons are true, respectively. The results from these functions are sure to be length 1 so they are appropriate for use in if clauses, while the results from the vectorized comparison are not. (Though those results would be appropriate for use in ifelse.)

One final difference: the && and || only evaluate as many terms as they need to (which is often called short-circuiting). For example, here's a comparison using an undefined value a; if it didn't short-circuit, as & and | don't, it would give an error.

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

Finally, see section 8.2.17 in The R Inferno, titled "and and andand".

Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
  • I'm comparing logicals of length 1. The documentation is not clear about why its preferred for control-flow. Is that because it uses the "short-circuit" from @Theo's answers and thus has better performance? – Suraj Jul 02 '11 at 19:21
  • nope. Just use the short form '&' -- the short-circuit answers are incorrect. – M. Tibbits Jul 02 '11 at 19:25
  • 2
    No, because it guarantees to have only a single TRUE/FALSE answer. The shorter forms could result in `c(TRUE, FALSE)`, and the `if` statement wouldn't be clear. If you are certain everything has length 1, then yes, either would do, and you are correct that the "short-circuit" is the reason for preferring one. A word of warning though, make sure you are 100% sure they can only be length one. You can get really goofy bugs otherwise. – Aaron left Stack Overflow Jul 02 '11 at 19:28
  • 11
    @SFun28: Yes, short-circuiting is the reason it preferred for flow control. As well as better performance, you may not want to evaluate all arguments. The canonical example is given in `?is.R` for checking whether you are running R or S-Plus. `if(exists("is.R") && is.function(is.R) && is.R())`. If `is.R` doesn't exist, then you don't want to evaluate `is.function(is.R)` since it will throw an error. Likewise if `is.R` isn't a function, you don't want to call it as though it is. – Richie Cotton Jul 04 '11 at 12:49
  • 3
    In the current version of the R inferno, the relevant section is now 8.2.17 "and and andand" – Silverfish Mar 07 '14 at 14:49
  • In the current version of R, `((-2:2) >= 0) && ((-2:2) <= 0)` doesn't return `FALSE` but an error instead: `'length = 5' in coercion to 'logical(1)'`. – robertspierre Jul 18 '23 at 13:31
  • @robertspierre In 4.2.1 this is a warning, not an error; has that changed now in 4.3.1? – Aaron left Stack Overflow Jul 18 '23 at 13:36
  • @AaronleftStackOverflow yes, see my answer – robertspierre Jul 18 '23 at 15:20
48

The answer about "short-circuiting" is potentially misleading, but has some truth (see below). In the R/S language, && and || only evaluate the first element in the first argument. All other elements in a vector or list are ignored regardless of the first ones value. Those operators are designed to work with the if (cond) {} else{} construction and to direct program control rather than construct new vectors.. The & and the | operators are designed to work on vectors, so they will be applied "in parallel", so to speak, along the length of the longest argument. Both vectors need to be evaluated before the comparisons are made. If the vectors are not the same length, then recycling of the shorter argument is performed.

When the arguments to && or || are evaluated, there is "short-circuiting" in that if any of the values in succession from left to right are determinative, then evaluations cease and the final value is returned.

> 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

The advantage of short-circuiting will only appear when the arguments take a long time to evaluate. That will typically occur when the arguments are functions that either process larger objects or have mathematical operations that are more complex.

Update: The most recent edition of news(“R”) says that supplying vectors of length greater than 1 to && or || is deprecated with a warning and the intent of RCore is to make it an error in a subsequent version of R.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • "short-circuiting" is a new term to me, but it seems to me that the answer describing it agrees with what you say about `&&` and `||`. – Aaron left Stack Overflow Jul 02 '11 at 19:22
  • @DWin - in the case of operatoring over length 1 logicals, they are equivalent right? I'm trying to understand why they are preferred in control-flow as the documentation states. Also, does R have a "short-circuit" construct? – Suraj Jul 02 '11 at 19:23
  • They are **NOT** equivalent for vectors of length > 1 – M. Tibbits Jul 02 '11 at 19:26
  • 2
    It is true that if the arguments to `&&` are functions and the first one is false, then the second one will not be evaluated. That is not true for either `&` or `ifelse` which will evaluate both arguments. – IRTFM Jul 02 '11 at 19:29
  • Isn't that what Theo's answer about short-circuiting says too? – Aaron left Stack Overflow Jul 02 '11 at 19:36
  • @DWin, you have just said that `&&` is short circuiting, but in your answer you say that they are not, make up your mind. – Theo Jul 02 '11 at 19:36
  • @Theo. I was misinterpreting your answer. I wasn't the only one so I hope my revised explanation is better. – IRTFM Jul 02 '11 at 19:40
  • Another example along the same lines: `if (!print(1) & print(2)) print(3)` returns 1 and 2 while `if (!print(1) && print(2)) print(3)` returns 1. – papgeo Aug 29 '18 at 09:35
  • "if any of the values in succession from left to right are determinative, then evaluations cease". I understand this in principle, but why then do the 3rd & 4th examples return 1? TRUE (first value) is determinative thus shouldn't it jump to the first `expr` and return 2 in both cases? Or is this an odd case due to use of `print` as a logically-evaluable condition? – dez93_2000 Feb 11 '21 at 18:05
  • 1
    @dez93 TRUE is not determinative when it precedes "&&". And those are not really returning 1 but rather 1 is being printed as a side-effect of the evaluation of the `print` function before the 2 and 3 are returned respectively. The 1 is being printed as a sign that the TRUE' were not determinative at that point. There was no 1 printed to the console in the 5th instance because the FALSE was determinative for the "&&" expression since the value of a second argument would not matter. If I had assigned the result of the if clause to a named variable we could have seen the situation more clearly. – IRTFM Feb 11 '21 at 21:52
  • Right, sorry yeah: so because the whole COND needs to evaluate TRUE to trigger the first EXPR, COND1=FALSE is determinitive (COND can't be TRUE) but COND1=TRUE isn't (because COND2 could still be FALSE). Cheers. – dez93_2000 Feb 12 '21 at 03:26
  • The curly brackets are not necessary – Julien Oct 02 '22 at 07:03
31

&& and || are what is called "short circuiting". That means that they will not evaluate the second operand if the first operand is enough to determine the value of the expression.

For example if the first operand to && is false then there is no point in evaluating the second operand, since it can't change the value of the expression (false && true and false && false are both false). The same goes for || when the first operand is true.

You can read more about this here: http://en.wikipedia.org/wiki/Short-circuit_evaluation From the table on that page you can see that && is equivalent to AndAlso in VB.NET, which I assume you are referring to.

Theo
  • 131,503
  • 21
  • 160
  • 205
  • 3
    This should be proof enough that it is short circuiting: `f <- function() { print('hello'); TRUE }; FALSE && f()`. Change to `&` and notice that the function is evaluated. QED. – Theo Jul 02 '11 at 19:32
  • 2
    Theo, yes, you are correct that `&&` and `||` short-circuit. But that's really a fairly minor point in comparisons between the short form and the long form; it's much more important to understand what each does when the inputs are vectors. – Aaron left Stack Overflow Jul 02 '11 at 19:37
  • 2
    @MTibbits In fact this is not a complete answer, but the statement about short circuiting **is correct**. Try `F & {message("Boo!");T}` and `F && {message("Boo!");T}`. – mbq Jul 02 '11 at 19:39
3

There are three relevant differences between the operators &&/|| and &/|, which are explained in the official documentation. Here’s a summary:

1. & and | are vectorised

This means that if you want to perform element-wise logical operations on vectors you should use & and |:

a = c(TRUE, TRUE, FALSE, FALSE)
b = c(TRUE, FALSE, TRUE, FALSE)

a | b
# [1]  TRUE  TRUE  TRUE FALSE

a || b
# [1] TRUE

For &&/|| all elements after the first are discarded. Recent versions of R generate a helpful warning when using &&/|| on vectors longer than 1:

In a || b : 'length(x) = 4 > 1' in coercion to 'logical(1)'

2. && and || are short-circuited

Short-circuiting means that the right-hand side of the expression is only evaluated if the left-hand side does not already determine the outcome. Pretty much every programming language does this for conditional operations, since it leads to handy idioms when writing if conditions, e.g.:

if (length(x) > 0L && x[1L] == 42) …

This code relies on short-circuiting: without it, the code would fail if x is empty, since the right-hand side attempts to access a non-existent element. Without short-circuiting, we would have to use nested if blocks, leading to more verbose code:

if (length(x) > 0L) {
    if (x[1L] == 42) …
}

As a general rule, inside a conditional expression (if, while) you should always use && and ||, even if short-circuiting isn’t required: it’s more idiomatic, and leads to more uniform code.

3. & and | can perform bitwise arithmetic

In many (most?) programming languages, & and | actually perform bitwise arithmetic instead of Boolean arithmetic. That is, for two integers a and b, a & b calculates the bitwise and, and a | b calculates the bitwise or. For Boolean values there’s no difference between bitwise and logical operations; but for arbitrary integers, the result differs. For instance, 1 | 2 == 3 in most programming languages.

However, this is not true for R: R coerces numeric arguments of & and | to logical values and performs Boolean arithmetic.

… except when both arguments are of type raw:

c(1, 3) | c(2, 4)
# [1] TRUE TRUE

as.raw(c(1, 3)) | as.raw(c(2, 4))
# [1] 03 07

It is worth noting that the operations ! (logical negation) and xor also perform bitwise arithmetic when called with raw arguments.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
1

From the changelog, since R 4.2.0 calling && or || with arguments of length greater than one is a warning:

Calling && or || with either argument of length greater than one now gives a warning (which it is intended will become an error).

and since 4.3.0 is an error:

Calling && or || with LHS or (if evaluated) RHS of length greater than one is now always an error, with a report of the form

'length = 4' in coercion to 'logical(1)'

Environment variable R_CHECK_LENGTH_1_LOGIC2 no longer has any effect.

robertspierre
  • 3,218
  • 2
  • 31
  • 46