I would like to use R's fn_env()
with a string argument, for example my_fn_env("count")
. The users of the program can enter any function, and may also include functions with the ::
notation, e.g., "plyr::count"
, so that this function should return the same as fn_env(plyr::count)
I considered this:
do.call("fn_env", list("plyr::count"), quote=FALSE)
but the quoted string given as an argument remains quoted. Chapter 7 of the e-book "Advanced R" (here) has a function where()
which returns the environment when a match is found, accepting strings, but it does not accept the ::
notation, apparently.
Any suggestions?
Sure, we can write a function that does that!
First, split the input string on ::
It then uses get()
or getExportedValue()
to retrieve the actual function.
Finally, it returns the environment of that function.
This should give you the same results as using fn_env() directly on the function, but with the flexibility of accepting string inputs.
using<-function(...) {
libs<-unlist(list(...))
req<-unlist(lapply(libs,require,character.only=TRUE))
need<-libs[req==FALSE]
if(length(need)>0){
install.packages(need)
lapply(need,require,character.only=TRUE)
}
}
using("rlang")
my_fn_env <- function(fun_name) {
# Split the string in case it contains namespace specification
parts <- strsplit(fun_name, "::")[[1]]
if (length(parts) == 1) {
# Case 1: Regular function name without namespace
fn <- tryCatch(
get(fun_name, mode = "function"),
error = function(e) stop("Function '", fun_name, "' not found")
)
return(environment(fn))
} else if (length(parts) == 2) {
# Case 2: Function with namespace specification
pkg <- parts[1]
fun <- parts[2]
# Check if package is installed and loaded
if (!requireNamespace(pkg, quietly = TRUE)) {
stop("Package '", pkg, "' is not installed")
}
# Get the function from the namespace
fn <- tryCatch(
getExportedValue(pkg, fun),
error = function(e) stop("Function '", fun, "' not found in package '", pkg, "'")
)
return(environment(fn))
} else {
stop("Invalid function name format")
}
}
# normal way using fn_env
f <- function(x) x + y
fn_env(f)
# Test our function!
my_fn_env("f")
my_fn_env("mean")
my_fn_env("plyr::count")