Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the "conditional or" (also called "short-circuit or"), written as `||` operator work in R?

Tags:

r

So, how does the "conditional or" (also called "short-circuit or"), written as || operator work in R?

Querying ?Logic reveals:

& and && indicate logical AND and | and || indicate logical OR. The shorter form performs elementwise comparisons in much the same way as arithmetic operators. The longer form evaluates left to right examining only the first element of each vector. Evaluation proceeds only until the result is determined. The longer form is appropriate for programming control-flow and typically preferred in if clauses.

Sounds standard.

> library(dplyr)
> as_tibble(mtcars) %>% filter(between(hp,50,70))
# A tibble: 5 x 11
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1  24.4     4 147.     62  3.69  3.19  20       1     0     4     2
2  32.4     4  78.7    66  4.08  2.2   19.5     1     1     4     1
3  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
4  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
5  27.3     4  79      66  4.08  1.94  18.9     1     1     4     1

Ok.

> as_tibble(mtcars) %>% filter(between(hp,80,90))
# A tibble: 0 x 11
# … with 11 variables: mpg <dbl>, cyl <dbl>, disp <dbl>, hp <dbl>, drat <dbl>, ...
#   carb <dbl>

Ok. Let's try the standard or |, which is equivalent to set union here:

> as_tibble(mtcars) %>% filter(between(hp,50,70) | between(hp,80,90))
# A tibble: 5 x 11
    mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1  24.4     4 147.     62  3.69  3.19  20       1     0     4     2
2  32.4     4  78.7    66  4.08  2.2   19.5     1     1     4     1
3  30.4     4  75.7    52  4.93  1.62  18.5     1     1     4     2
4  33.9     4  71.1    65  4.22  1.84  19.9     1     1     4     1
5  27.3     4  79      66  4.08  1.94  18.9     1     1     4     1

Ok. Let's try the conditional or ||, which should give the same result (|| should never change semantics, only computation efficiency, except in the border case of partial function etc.):

> as_tibble(mtcars) %>% filter(between(hp,50,70) || between(hp,80,90))
# A tibble: 0 x 11
# … with 11 variables: mpg <dbl>, cyl <dbl>, disp <dbl>, hp <dbl>, drat <dbl>, ...
#   carb <dbl>

What is this weirdness? between(hp,50,70) || between(hp,80,90) yields TRUE nowhere?

like image 262
David Tonhofer Avatar asked Oct 15 '19 09:10

David Tonhofer


People also ask

What is short circuit in logical operators?

Logical Short-Circuiting. The logical or operator returns logical 1 ( true) if even a single condition in the expression is true. When the evaluation of a logical expression terminates early by encountering one of these values, the expression is said to have short-circuited.

How to evaluate and and or statements using short circuit?

Short-circuit is a tricky method for evaluating logical operators AND and OR. In this method, the whole expression can be evaluated to true or false without evaluating all sub expressions. In the above program both operands Condition1 () and Condition2 () are evaluated.

What is a short-circuited logical expression?

The logical or operator returns logical 1 ( true) if even a single condition in the expression is true. When the evaluation of a logical expression terminates early by encountering one of these values, the expression is said to have short-circuited.

What is the conditional logical OR operator ||?

The conditional logical OR operator ||, also known as the "short-circuiting" logical OR operator, computes the logical OR of its operands. The result of x || y is true if either x or y evaluates to true. Otherwise, the result is false.


1 Answers

The || operator only compares the first elements of vectors, and returns a single logical result, while | compares vectors elementwise, and returns a vector result. See, e.g.:

x <- c(FALSE, TRUE)
y <- c(FALSE, FALSE)

x | y
#> [1] FALSE  TRUE
x || y
#> [1] FALSE

This is actually also mentioned in the help text you quoted: “The longer form evaluates left to right examining only the first element of each vector.” [emphasis added]

Created on 2019-10-15 by the reprex package (v0.3.0)

like image 162
Mikko Marttila Avatar answered Nov 15 '22 10:11

Mikko Marttila