2

I know the part that && and || make for more efficient code because they do the least number of tests in a chain and break out as soon as we have enough information to know what the result of the chain is going to be.

  • As soon as && hits a FALSE in a chain it stops evaluating and returns FALSE for the whole chain.
  • As soon as || hits a TRUE in a chain it stops evaluating and returns TRUE for the chain

But I read in Garrett Grolemund's book that "...double operators are not appropriate everywhere. && and || are not vectorized, which means they can only handle a single logical test on each side of the operator..." Can somebody please explain to me what the emphasized part means?

Did some simple tests and while & is doing a element-wise comparison between the corresponding elements of the two logical vectors, && is comparing only the first elements and returning TRUE because the operator is not vecorized? Is that all the emphasized part above means, or is there more to it?

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

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

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

Collapsing vectors on either side of the operator to one boolean value using any and all.

any(T, T, F, F, T) && all(F, F, T, T, T)
[1] FALSE

any(T, T, F, F, T) && any(F, F, T, T, T)
[1] TRUE
computronium
  • 445
  • 2
  • 11
  • 1
    *&& is comparing only the first elements and returning TRUE because the operator is not vecorized?* Yes, that's it, the all of it. And your tests are well designed but I would include a test like the second one with a `F` as first element of one of the vectors, `c(T, F, F, F, F) && c(F, T, F, T, F)`. Also, both `any` and `all` return values have length == 1, so there's only one element to compare. – Rui Barradas Feb 14 '20 at 07:35
  • Also, include a link to Garreth Grolemund's book, please, he has more than one. – Rui Barradas Feb 14 '20 at 07:38
  • Did several other tests on the console. But didn't include here to keep the question short. Editing and adding for demonstrative purposes in case someone else has this doubt. Thanks – computronium Feb 14 '20 at 07:42

1 Answers1

6

they can only handle a single logical test on each side of the operator

a <- c(T, F, F, F)
b <- c(T, F, F, F)
a && b

Returns [1] TRUE

Because only the first element of a and b are tested!

Edit:

Consider the following, where we 'rotate' a and b after each && test:

a <- c(T, F, T, F)
b <- c(T, F, F, T)
for (i in seq_along(a)){
  cat(paste0("'a' is: ", paste0(a, collapse=", "), " and\n'b' is: ", paste0(b, collapse=", "),"\n"))
  print(paste0("'a && b' is: ", a && b))
  a <- c(a[2:length(a)], a[1])
  b <- c(b[2:length(b)], b[i])
}

Gives us:

'a' is: TRUE, FALSE, TRUE, FALSE and
'b' is: TRUE, FALSE, FALSE, TRUE
[1] "'a && b' is: TRUE"
'a' is: FALSE, TRUE, FALSE, TRUE and
'b' is: FALSE, FALSE, TRUE, TRUE
[1] "'a && b' is: FALSE"
'a' is: TRUE, FALSE, TRUE, FALSE and
'b' is: FALSE, TRUE, TRUE, FALSE
[1] "'a && b' is: FALSE"
'a' is: FALSE, TRUE, FALSE, TRUE and
'b' is: TRUE, TRUE, FALSE, TRUE
[1] "'a && b' is: FALSE"

Additionally, &&, || stops as soon as the expression is clear:

FALSE & a_not_existing_object
TRUE | a_not_existing_object

Returns:

Error: object 'a_not_existing_object' not found
Error: object 'a_not_existing_object' not found

But:

FALSE && a_not_existing_object
TRUE || a_not_existing_object

Returns:

[1] FALSE

[1] TRUE

Because anything after FALSE AND something (and TRUE OR something) becomes FALSE and TRUE respectively

This last behavior of && and || is especially useful if you want to check in your control-flow for an element that may not exist:

if (exists(a_not_existing_object) && a_not_existing_object > 42) {...}

This way the evaluation stops after the first expression evaluates to FALSE and the a_not_existing_object > 42 part is not even atempted!

dario
  • 6,415
  • 2
  • 12
  • 26
  • update from https://cran.r-project.org/doc/manuals/r-devel/NEWS.html ; this will produce a warning in r 4.2.0 and will become an error in the future – user20650 Apr 25 '22 at 12:52