Programmatically switch package in `::` call in R

Since :: can be seen as a function, it looks like

`::`(dummy_pkg_name, foo)()

is what you want. Alternatively,

getFromNamespace("foo", ns = dummy_pkg_name)()

For instance,

`::`(stats, t.test)
# function (x, ...) 
# UseMethod("t.test")
# <bytecode: 0x102fd4b00>
# <environment: namespace:stats>

getFromNamespace("t.test", ns = "stats")
# function (x, ...) 
# UseMethod("t.test")
# <bytecode: 0x102fd4b00>
# <environment: namespace:stats>

You could also create a call() that could then be evaluated.

call("::", quote(bar), quote(foo()))
# bar::foo()

Put into use:

c <- call("::", quote(stats), quote(t.test))
eval(c)
# function (x, ...) 
# UseMethod("t.test")
# <bytecode: 0x4340988>
# <environment: namespace:stats>

Wrapped up in a function using setdiff as our default function:

f <- function(pkg, fn = setdiff) {
    pkg <- substitute(pkg)
    fn <- substitute(fn)
    eval(call("::", pkg, fn))
}

f(base)
# function (x, y) 
# {
#     x <- as.vector(x)
#     y <- as.vector(y)
#     unique(if (length(x) || length(y)) 
#         x[match(x, y, 0L) == 0L]
#     else x)
# }
# <bytecode: 0x30f1ea8>
# <environment: namespace:base>

f(dplyr)
# function (x, y, ...) 
# UseMethod("setdiff")
# <environment: namespace:dplyr>

To adhere to KISS, simply re-assign to new named functions in global environment. Be sure to leave out () since you are not requesting to run the function.

parent_foo <- parentPkg::foo
child1_foo <- childPkg1::foo
child2_foo <- childPkg2::foo
child3_foo <- childPkg3::foo

Then, conditionally apply them as needed:

if (scenario=="child1") {
  obj <- child1_foo(...)
} 
else if (scenario=="child2") {
  obj <- child2_foo(...)
} 
...

Tags:

R

Package