Thanks to @joran for pointing me to this excellent article that explained to me why %in% did not use my new match function. Here is my understanding of what is going on:
The user- match function is stored in the global environment, and the original match function is stored in namespace:base :
environment(match) # <environment: R_GlobalEnv> environment(base::match) # <environment: namespace:base>
Now consider what happens when I call m %in% c(2, 3) :
- Executes the function
%in% , which is defined as function(x, table) match(x, table, nomatch = 0L) > 0L . - The function must find the
match function, so it first searches in its local environment, which was created as part of the function call. match is not defined there. - The next place to look for
match is the function environment. We can understand what it is:
environment(`%in%`) # <environment: namespace:base>
- Since the original version of
match (and not the user version) is defined in namespace:base , this is the version of the function being called.
To work with my matrix version of %in% , the easiest approach is to follow @Molx's recommendations and override %in% to be stored in a global environment (note that there is still an identical version of the function in namespace:base ):
`%in%` <- function(x, table) match(x, table, nomatch = 0L) > 0L environment(`%in%`) # <environment: R_GlobalEnv>
Now m %in% c(2, 3) will look for the match function first in its local functional environment, and then in the environment ( R_GlobalEnv ), finding our custom version of the match function:
m %in% c(2, 3) # [,1] [,2] # [1,] FALSE TRUE # [2,] TRUE FALSE
Another way we could use %in% to use the custom match function would be to change the environment of base::"%in%" in the global environment:
rm(`%in%`) # Remove user-defined %in% environment(`%in%`) <- .GlobalEnv # Can be reversed with environment(`%in%`) <- asNamespace("base") m %in% c(2, 3) # [,1] [,2] # [1,] FALSE TRUE # [2,] TRUE FALSE
As @Molx commentators have already pointed out, the most sensible thing is to avoid all this headache by calling my new function something like %inm% .