mschilli
mschilli

Reputation: 1894

get name of function assigned to variable in R

I have a similar question as this one, but a more special case.

Consider the following example code:

fun1 <- mean
fun2 <- max
fun3 <- median

Now I want to get the names of the functions assigned to the variables as charachters.

While I understand that this is not possible in general, the above case seems somewhat special:

l <- list(fun1 = fun1, fun2 = fun2, fun3 = fun3)
l
$fun1
function (x, ...)
UseMethod("mean")
<bytecode: 0x2793818>
<environment: namespace:base>
$fun2
function (..., na.rm = FALSE)  .Primitive("max")
$fun3
function (x, na.rm = FALSE)
UseMethod("median")
<bytecode: 0x28382c8>
<environment: namespace:stats>

So the output of print(funX) contains the name of the function assigned to funX.

How can I extract this information into a character vector?

Upvotes: 1

Views: 387

Answers (3)

user2276686
user2276686

Reputation: 2076

for (myfun in c(max,mean,median))
  print(gsub('^.*"(.*)".*','\\1',tail(deparse(myfun),1)))

Upvotes: 0

mschilli
mschilli

Reputation: 1894

The best I could come up with so far is parsing the print output:

get_fun <- function(fun){
             lines <- capture.output(print(fun))
             pat <- "UseMethod|Primitive"
             index <- grep(pat, lines)
             line <- lines[index]
             pat <- paste0(".*(", pat, ")")
             chunk <- sub(pat, "", line)
             words <- strsplit(chunk, "\"")[[1]]
             return(words[2])
           }
sapply(l, get_fun)
    fun1     fun2     fun3
  "mean"    "max" "median"

But there has to be a more direct way. After all somehow these names make it to the print output in the first place.


edit: Based on Roland's answer, I was able to simplify the above function definition to the following:

get_fun <- function(fun){
             fun <- deparse(fun)
             chunk <- tail(fun, 1)
             words <- strsplit(chunk, "\"")[[1]]
             return(words[2])
           }

Still I hope for a more direct/robust solution (as a higher-order function, maybe returning "fun" for cases were the real underlying function can not be determined/does not exist).

Upvotes: 0

Roland
Roland

Reputation: 132576

Use findGeneric for the S3 generics:

fun1 <- mean

utils:::findGeneric("fun1", parent.frame())
#[1] "mean"

For a primitive function you can deparse the function body:

fun2 <- max
is.primitive(fun2)
#[1] TRUE

body <- deparse(fun2)
m <- gregexpr('(?<=\\.Primitive\\(\\").*(?=\\")', body, perl = TRUE)
regmatches(body, m)[[1]]
#[1] "max"

Upvotes: 1

Related Questions