2

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
  • 3,735
  • 7
  • 46
  • 90

2 Answers2

11

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,693
  • 1
  • 21
  • 29
4

| is vectorised, || isn’t (it only looks at the first element):

> a = c(TRUE, TRUE, FALSE, FALSE)
> b = c(TRUE, FALSE, TRUE, FALSE)
> a | b
[1]  TRUE  TRUE  TRUE FALSE
> a || b
[1] TRUE

In addition, || and | preserve the respective properties they have in other languages, meaning ||’s evaluation is short-circuited while |’s isn’t:

> f = function() { cat('f\n'); TRUE }
> f() || f()
f
[1] TRUE
> f() | f()
f
f
[1] TRUE
Konrad Rudolph
  • 506,650
  • 124
  • 909
  • 1,183
  • @JoshuaUlrich I randomly came back to this answer and I realise that I have no idea what your comment means: I mention vectorisation and short-circuiting … what else is there? – Konrad Rudolph Jan 19 '21 at 18:41
  • @JoshuaUlrich OK, I thought there might be something else. My condolences about your memory. ;-) – Konrad Rudolph Jan 21 '21 at 15:01