Why TRUE == "TRUE" is TRUE in R?
Is there any equivalent for === in R?
Update:
These are all returning FALSE:
TRUE == "True"
TRUE == "true"
TRUE == "T"
The only TRUE value is TRUE == "TRUE".
In case of checking with identical() everything works fine.
Second Update:
By === operator I meant the process of checking the Value and the Data Type of a variable. In this case I assumed that the == operator will only compare the Values of variables, not their Data Type as well.
According to the help file ?`==` :
If the two arguments are atomic vectors of different types, one is coerced to the type of the other, the (decreasing) order of precedence being character, complex, numeric, integer, logical and raw.
So TRUE is coerced to "TRUE" (i. e. as.character(TRUE)), hence the equality.
The equivalent of an operator === in some other language (i. e. are the two objects equal and of the same type) would be function identical:
identical(TRUE, "TRUE")
[1] FALSE
TRUE and FALSE are reserved words in R. I don't think eznme was correct (before his edit) when he said any non-zero value was TRUE, since TRUE == "A" evaluates to FALSE. (That would have been correct in explaining why TRUE == 1 evaluates to TRUE, but it would not explain the result for TRUE == 7
The explanation given by plannapus was taken out of the context of describing the behavior of as.logical. It is closer to the "truth", because it is the implicit coercion of TRUE to character by the == operator that creates this result. Although T and F are initially given the values of TRUE and FALSE, they can be reassigned to other values or types.
> TRUE == as.logical( c("TRUE", "T", "true", "True") )
[1] TRUE TRUE TRUE TRUE
> TRUE == 7
[1] FALSE
> TRUE == as.logical(7)
[1] TRUE
> TRUE == as.logical("A")
[1] NA
(I earlier incorrectly wrote that the coercion induced by TRUE == "TRUE" was to logical; it's actually via as.character(TRUE) returning "TRUE".)
In addition to
TRUE == "TRUE"
these are also true:
TRUE==1
TRUE==1.0
TRUE==1.0000000000000001
TRUE==0.99999999999999999
etc, in general also all values close enough to 1.0 to be IEEE754-rounded to it.
But what is more interesing is what if() checks: it checks non-false; in fact this plots!:
if(4.0) plot(1)
I think the only values that dont trigger if() are 0, F, FALSE and "FALSE" they seem defined as exactly 0.
Related
If I understand, rlang::quo_is_missing evaluates a quosure and checks whether it contains a missing value. If it does, it should return TRUE, FALSE if not. Yet, I've tried the following combinations and it always returns FALSE:
rlang::quo_is_missing(quo(NA))
rlang::quo_is_missing(quo(NA_character_))
rlang::quo_is_missing(quo(NA_integer_))
If I try non-NA values, it also returns FALSE, as expected:
rlang::quo_is_missing(quo("hello"))
Why is it returning FALSE when the value is obviously missing?
"Missing" is a special term that refers to values that are not present at all. NA is not the same as "missing" -- NA is itself a value. In base R you can compare the functions is.na() and missing() each of which do different things. quo_is_missing is like the missing() function, not is.na and returns true only when there is no value at all:
rlang::quo_is_missing(quo())
If you want to check for NA, you could write a helper
quo_is_na <- function(x) {
!rlang::quo_is_symbolic(x) &&
!rlang::quo_is_missing(x) &&
!rlang::quo_is_null(x) &&
is.na(rlang::quo_get_expr(x))
}
quo_is_na(quo())
# [1] FALSE
quo_is_na(quo(x+y))
# [1] FALSE
quo_is_na(quo(NULL))
# [1] FALSE
quo_is_na(quo(42))
# [1] FALSE
quo_is_na(quo(NA))
# [1] TRUE
quo_is_na(quo(NA_character_))
# [1] TRUE
Why TRUE == "TRUE" is TRUE in R?
Is there any equivalent for === in R?
Update:
These are all returning FALSE:
TRUE == "True"
TRUE == "true"
TRUE == "T"
The only TRUE value is TRUE == "TRUE".
In case of checking with identical() everything works fine.
Second Update:
By === operator I meant the process of checking the Value and the Data Type of a variable. In this case I assumed that the == operator will only compare the Values of variables, not their Data Type as well.
According to the help file ?`==` :
If the two arguments are atomic vectors of different types, one is coerced to the type of the other, the (decreasing) order of precedence being character, complex, numeric, integer, logical and raw.
So TRUE is coerced to "TRUE" (i. e. as.character(TRUE)), hence the equality.
The equivalent of an operator === in some other language (i. e. are the two objects equal and of the same type) would be function identical:
identical(TRUE, "TRUE")
[1] FALSE
TRUE and FALSE are reserved words in R. I don't think eznme was correct (before his edit) when he said any non-zero value was TRUE, since TRUE == "A" evaluates to FALSE. (That would have been correct in explaining why TRUE == 1 evaluates to TRUE, but it would not explain the result for TRUE == 7
The explanation given by plannapus was taken out of the context of describing the behavior of as.logical. It is closer to the "truth", because it is the implicit coercion of TRUE to character by the == operator that creates this result. Although T and F are initially given the values of TRUE and FALSE, they can be reassigned to other values or types.
> TRUE == as.logical( c("TRUE", "T", "true", "True") )
[1] TRUE TRUE TRUE TRUE
> TRUE == 7
[1] FALSE
> TRUE == as.logical(7)
[1] TRUE
> TRUE == as.logical("A")
[1] NA
(I earlier incorrectly wrote that the coercion induced by TRUE == "TRUE" was to logical; it's actually via as.character(TRUE) returning "TRUE".)
In addition to
TRUE == "TRUE"
these are also true:
TRUE==1
TRUE==1.0
TRUE==1.0000000000000001
TRUE==0.99999999999999999
etc, in general also all values close enough to 1.0 to be IEEE754-rounded to it.
But what is more interesing is what if() checks: it checks non-false; in fact this plots!:
if(4.0) plot(1)
I think the only values that dont trigger if() are 0, F, FALSE and "FALSE" they seem defined as exactly 0.
I'm trying to understand the ! operator better in R, and I'm confused as to how it applies to numbers. What does the following code signify, and why are the two equality queries not the same?
> !5 == 7
[1] TRUE
> 5 == !7
[1] FALSE
> !5
[1] FALSE
Thanks!
First of all: the ! operator coerces non-logicals to logical, then reverses them. Anything other than 0 evaluates to a logical TRUE, then the ! operator flips it to FALSE
The rest has to do with order of operations.
!5 == 7
Evaluates to
!(5==7)
Which is equivalent to
!(FALSE)
Which returns TRUE
Whereas
5 == !7
Evaluates to
5 == FALSE
Which returns FALSE
The equivalent to 5 == !7 would be (!5) == 7 (Both return FALSE)
The ! coerces its argument to a logical, thus:
as.logical(-3L:3L)
# [1] TRUE TRUE TRUE FALSE TRUE TRUE TRUE
as.logical(seq(-2,2, by = 0.5))
# [1] TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE
As you can see, 0 is FALSE, everything else is TRUE.
To get an even better sense of this, see that ! is - like everything in R - a function:
> `!`
function (x) .Primitive("!")
So, you're applying the ! function to numeric arguments, which are coerced to logical, as above.
When you compare a logical to a numeric value using ==, the numeric value is also coerced to logical.
In your first example (!5 == 7) is due to precedence ordering; == is higher precedence than !.
When passing only a single vector to the logical and/or operator, the operator negates the argument:
> x = c(F,T,T)
> `&`(x)
[1] TRUE FALSE FALSE
> `|`(x)
[1] TRUE FALSE FALSE
To make the logical operator work as idempotent, one needs to pass a single element vector as the second argument:
> `&`(x,T)
[1] FALSE TRUE TRUE
> `|`(x,F)
[1] FALSE TRUE TRUE
Why do the logical operators negate their argument when there is only one argument passed?
This was modified in R 3.2.1 as a result of a bug report. As you've pointed out, the previous behavior made little sense:
If there are multiple boolean expressions as arguments to the which function, are they evaluated lazily?
For example:
which(test1 & test2)
If test1 returns false, then test2 is not evaluated as the compound expression will be false anyway.
With if there can be efficiency gains as a result of that behavior. It is documented to work that way, and I don't think it is due to lazy evaluation. Even if you "force()-ed" that expression it would still only evaluate a series of &'s until it had a single FALSE. See this help page:
?Logic
#XuWang probably deserved the credit for emphasizing the difference between "&" and "&&". The "&" operator works on vectors and returns vectors. The "&&" operator acts on scalars (actually vectors of length==1) and returns a vector of length== 1. When offered a vector or length >1 as either side of the arguments, it will work on only the information in the first value of each and emit a warning. It is only the "&&" version that does what is being called "lazy" evaluation. You can see that hte "&" operator is not acting in a "lazy fashion with a simepl test:
fn1 <- function(x) print(x)
fn2 <- function(x) print(x)
x1 <- sample(c(TRUE, FALSE), 10, replace=TRUE)
fn1(x1) & fn2(x1) # the first two indicate evaluation of both sides regardless of first value
# [1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE FALSE
# [1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE FALSE
# [1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE FALSE