4

Why does NULL == 1 returns logical(0) instead of FALSE?

identical(1, NULL) returns FALSE, which is correct.

I know that == and identical cannot be used interchangeably, but what goes behind NULL == 1 returning logical(0)?

Zheyuan Li
  • 71,365
  • 17
  • 180
  • 248
FinThusiast
  • 139
  • 8

1 Answers1

5

There is an implicit type-coercion behind "==" (or any other logical operators) when two operands don't have the same mode. From ?"==":

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".

This can give you some unbelievable result!

"0" == 0  ## TRUE
1L == 1.0 ## TRUE

Thus in ?identical, it is mentioned that "==" is not really doing what people suppose it to do.

identical does no coercion. In fact, if you just look at the examples in ?identical, you will see (I changed them a little bit):

identical(1, NULL) ## FALSE -- don't try this with ==
identical(1, 1L)   ## FALSE, stored as different types (modes)

NULL is amazingly versatile (or vague). See elaborations here. What happens in "==" is that NULL is coerced to numeric(0) because mode(1) is "numeric", and you are actually testing

numeric(0) == 1  ## NULL == 1
numeric(0) == c(1, 2)  ## NULL == c(1, 2)

Now the question is, why is the result logical(0)? Doesn't R's recycling rule (R-intro) applies? Why isn't the above code transformed to the following?

rep_len(numeric(0), 1) == 1  ## NA
rep_len(numeric(0), 2) == c(1, 2)  ## NA NA

Well, in recycling rule (R-lang), it is said:

As from R 1.4.0, any arithmetic operation involving a zero-length vector has a zero-length result.

Oh great; there is deliberately no recycling here. So we just get logical(0).

Zheyuan Li
  • 71,365
  • 17
  • 180
  • 248