############################################################################.
# & 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 43. & vs && and | vs ||
NOTE: We already covered this concept earlier. This just reviews the concept with additional examples.
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 truncError 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