43  43. & vs && and | vs ||

NOTE: We already covered this concept earlier. This just reviews the concept with additional examples.

############################################################################.
# & vs &&
# | vs ||
#
# There are two type of "and" operators and two types of "or" operators
# in R. 
#       The 1st type is & and |. 
#
#       The 2nd type is && and || (with doubled symbols).
#
# It is preferable to use the "doubled" operators for
# conditions in both "if statements" and in "while loops". 
# The reason is based on the following two fundamental differences between the
# single symbol operators & and | vs the double symbols operators && and ||
#
#
# *** FIRST DIFFERENCE ***
#
#   & and | are "vectorized operators" while && and || are not vectorized
#
#   The single & and | are vectorized (i.e. they will return an entire 
#   vector of multiple TRUE/FALSE values if necessary). In the following
#   example, there are two values in the answer
#
#      > c(TRUE, TRUE) & c(FALSE, TRUE)
#      [1] FALSE TRUE
#
#    By contrast, the double && and || operators only return 
#    the first TRUE or FALSE
#
#      > c(TRUE, TRUE) && c(FALSE, TRUE)
#      [1] FALSE 
#
#
# *** SECOND DIFFERENCE *** 
#   && and || are "shortcut operators", & and | are not.
#
#     The double && and || will only process the values up until an answer
#     can be figured out. We call these shortcut operators.
#
#     By contrast, the single & and | will process ALL values
#
# See examples below.
##########################################################################.

43.0.1 Example 1

#------------------------------.
# Examples for difference #1 
#------------------------------.

# & and | return multiple TRUE/FALSE values 
# (i.e. & and | are "vectorized" operators)

c(TRUE,TRUE,TRUE) | c(FALSE, TRUE, FALSE)
[1] TRUE TRUE TRUE
c(TRUE,TRUE,TRUE) & c(FALSE, TRUE, FALSE)
[1] FALSE  TRUE FALSE
# The double operators only return the first value for the answer.
#
# This is what you want for the conditions in "if statements" and
# in "while loops" since the entire condition should evaluate
# to a single TRUE or FALSE

c(TRUE,TRUE,TRUE) || c(FALSE, TRUE, FALSE)
Error in c(TRUE, TRUE, TRUE) || c(FALSE, TRUE, FALSE): 'length = 3' in coercion to 'logical(1)'
c(TRUE,TRUE,TRUE) && c(FALSE, TRUE, FALSE)
Error in c(TRUE, TRUE, TRUE) && c(FALSE, TRUE, FALSE): 'length = 3' in coercion to 'logical(1)'

43.0.2 Example 2 - isWholeNumber

#------------------------------.
# Examples for difference #2
#------------------------------.

# && and || use "shortcut" logic:
#
#   FALSE && ANYTHING  # The answer MUST BE FALSE
#
#   TRUE && ______     # I don't konw the answer until I analyze the ______
#
#
#
#
#   TRUE || ANYTHING  # The answer MUST BE TRUE
#
#   FALSE || ______     # I don't konw the answer until I analyze the ______



# In the following code, the trunc will not be processed if
# is.numeric is FALSE. This is appropriate since trunc would fail 
# with an error if it is passed a character value.
isWholeNumber = function( x ){
 tf = is.numeric(x) && trunc(x) == x 
 return (tf)
}

isWholeNumber(3.5)       # FALSE
[1] FALSE
isWholeNumber(3)         # TRUE
[1] TRUE
isWholeNumber(-3)         # TRUE
[1] TRUE
isWholeNumber(-3.5)         # TRUE
[1] FALSE
isWholeNumber("apple")   # FALSE  (this is correct)
[1] FALSE
# The following code incorrectly uses & 
# Therefore the code fails with an error when passed a
# character value.

isWholeNumber_bad = function( x ){
 tf = is.numeric(x) & trunc(x) == x 
 return (tf)
}

isWholeNumber_bad(3.5)       # FALSE
[1] FALSE
isWholeNumber_bad(3)         # TRUE
[1] TRUE
isWholeNumber_bad("apple")   # ERROR - non-numeric argument to trunc
Error in trunc(x): non-numeric argument to mathematical function

43.0.3 Example 3 - is.prime

# In general when using && and || in conditions for "if statements"
# and "while loops", use the double version (i.e. && and || 
# instead of & and |)

is.prime <- function( num ) {
  
  # DON'T DO THE FOLLOWING:
  #
  # if( !is.numeric(num) | trunc(num) != num | num < 1 ){
 
  # RATHER, DO THE FOLLOWING:
 
  if( length(num) != 1 || !is.numeric(num) || trunc(num) != num || num < 1 ){
    stop("num must be a single positive whole number")
  }
  
  if (num < 2){
    return(FALSE)
  }
  divisor <- 2
  
  while ( divisor <= sqrt(num) ) {
    if (num %% divisor == 0){
      return(FALSE)   
    }
    divisor <- divisor + 1
  }
  return(TRUE)
}

is.prime("apple")
Error in is.prime("apple"): num must be a single positive whole number
is.prime(c(100,200,300))
Error in is.prime(c(100, 200, 300)): num must be a single positive whole number
is.prime(23)
[1] TRUE
is.prime(27)
[1] FALSE

© 2025 Y. Rosenthal. All rights reserved.