4

I know that "||" means "or" in most programming languages, including R. But sometimes I see people using "|". And I am not entirely sure what it means. How is it different from "||" ?

Thanks

mynameisJEFF
  • 4,073
  • 9
  • 50
  • 96

2 Answers2

13

To get to the help for the logical operators in R you have to do

?`|`

or

?`||`

Both of which take you to the appropriate help page http://stat.ethz.ch/R-manual/R-patched/library/base/html/Logic.html

You won't notice a difference until you either put a vector in, or something that doesn't evaluate properly:

> T|F
[1] TRUE
> T||F
[1] TRUE

But when you use a vector:

> c(T,T,F,F) || c(T,F,T,F)
[1] TRUE
> c(T,T,F,F) | c(T,F,T,F)
[1]  TRUE  TRUE  TRUE FALSE

Similarly with & and &&:

> c(T,T,F,F) & c(T,F,T,F)
[1]  TRUE FALSE FALSE FALSE
> c(T,T,F,F) && c(T,F,T,F)
[1] TRUE

So | and & compare elements in corresponding positions in the two vectors and uses that to populate a new logical vector. If one vector is shorter than the other, its elements get "recycled" from the start:

> c(T, F, T, F) | c(T, T, F, F, T, F) #first 2 elements of left vector recycled
[1]  TRUE  TRUE  TRUE FALSE  TRUE FALSE
Warning message:
In c(T, F, T, F) | c(T, T, F, F, T, F) :
  longer object length is not a multiple of shorter object length
> c(T, F, T, F, T, F) | c(T, T, F, F, T, F) #what actually got evaluated
[1]  TRUE  TRUE  TRUE FALSE  TRUE FALSE

Note that || and && only look at the first element of the vectors, so for instance:

> c(T,T,T,T) && c(F,T,T,T) #only does T & F
[1] FALSE
> c(F,T,T,T) || c(F,T,T,T) #only does F | F
[1] FALSE
> c(T,F,F,F) && c(T,F,F,F) #only does T & T
[1] TRUE
> c(T,F,F,F) || c(F,F,F,F) #only does F | F
[1] TRUE

For inputs that can't be evaluated, || and && are cleverer: they "shortcircuit" from left to right. If the left-hand input of || is TRUE (so the result must be TRUE) or the left-hand input of && is FALSE (so the result must be FALSE) then right-hand input need not be evaluated.

> x
Error: object 'x' not found
> exists("x")
[1] FALSE
> F & x # evaluates right input, fails
Error: object 'x' not found
> F && x # skips right input, already knows result F
[1] FALSE
> T && x # can't skip right input, so fails
Error: object 'x' not found
> T | x
Error: object 'x' not found
> T || x # skips right input, already knows result T
[1] TRUE

This is useful if you want to check something safely:

> (x > 20)
Error: object 'x' not found
> exists("x") & (x > 20) # still evaluated right input, fails
Error: object 'x' not found
> exists("x") && (x > 20) # safe
[1] FALSE
Silverfish
  • 1,812
  • 1
  • 22
  • 30
9

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