Benefit of attaching objects (you can skip this)
In a sourced script, it can be convenient to define our helper funcs like this:
f <- function() print('hi')
e <- new.env()
assign("f", f, e)
rm(f)
attach(e)
rm(e)
Now, f is kind of protected. It does not clutter your global environment:
ls()
#> character(0) # if anything, no "f"
rm(f)
#> In rm(f) : object 'f' not found
But still e is on the search path:
search()
#> [1] ".GlobalEnv" "e" ... etc
So:
f()
#> [1] "hi"
Also, if we define another f in the global env, it takes precedence, but the attached function is protected from being deletes:
f <- function() print('hello')
f()
#> [1] "hello"
rm(f)
f()
#> [1] "hi" # again
To actually remove f remove (detach) its container:
detach(e)
f()
#> Error in f() : could not find function "f"
Attaching operators
Create a trivial infix operator
Consider the following operator definition:
`%plus%` <- function(x,y) UseMethod("%plus%")
`%plus%.numeric` <- function(x, y) x + y
1 %plus% 1
#> 2
Of course, that's for the sake of simplicity, but one can define a sophisticated %+% doing hard maths.
The issue
Let's try to attach our %plus% operator:
e <- new.env()
assign("%plus%.numeric", `%plus%.numeric`, e)
assign("%plus%", `%plus%`, e)
rm(`%plus%.numeric`)
rm(`%plus%`)
attach(e)
1 %plus% 1
gives:
Error in UseMethod("%plus%") :
no applicable method for '%plus%' applied to an object of class "c('double', 'numeric')"
Interestingly, the operator is visible:
`%plus%`
#> function(x,y) UseMethod("%plus%")
#> <bytecode: 0x557b338c86c0>
`%plus%.numeric`
#> function(x, y) x + y
And using the functional, rather than infix, form does work:
`%plus%.numeric`(1, 1)
#> 2
As user2554330 already points out in the comments, the issue arise not because of the infix operator but because of the method. You need to "register" the S3 method or it needs to be available in the environment of the call to the generic.
The documentation of
UseMethodelaborates on this:Created on 2024-01-28 with reprex v2.0.2