Berry Boessenkool
Berry Boessenkool

Reputation: 1538

Determining which Functions are in Code

I am trying to find which set of functions are used in some code.

Here's a minimal reproducible test:

code <- "mean(pi); head(data.frame(A=1:5)); data_frame(7:9)"
funs <- c("mean", "head", "head.data.frame",  "data.frame", "frame", "data_frame")

data.frame(isfound=sapply(paste0("[^a-zA-Z_\\.]",gsub(".","\\.",funs,fixed=TRUE),"\\("), 
                          grepl, x=paste0(" ",code)),
           shouldbefound=c(T,T,F,T,F,T))

This seems to work, but is too long and not very human-readable.
Is there a more elegant way to determine which of a set of functions appear in some code?

Upvotes: 1

Views: 59

Answers (1)

Sven Hohenstein
Sven Hohenstein

Reputation: 81733

You can use the following approach to find the names of the functions used in R code. The function get_functions can be used with code represented as character string.

get_functions <- function(code) {
  unname(find_functions(parse(text = code)))
}

find_functions <- function(x, y = vector(mode = "character", length = 0)) {
  if (is.symbol(x)) {
    if (is.function(eval(x)))
      c(y, as.character(x))
  } else {
    if (!is.language(x)) {
      NULL
    } else {
      c(y, unlist(lapply(x, find_functions)))
    }
  }
}

Here, find_functions is called recursively since expressions can be nested.

An example:

code <- "mean(pi); head(data.frame(A=1:5)); data_frame(7:9)\n paste(\"ABC\", 0x28)"

get_functions(code)
# [1] "mean"       "head"       "data.frame" ":"          "data_frame" ":"          "paste"

This approach appears to be more safe since it makes use of R's parser. Furthermore, functions without parentheses can be found too (e.g., :).

Upvotes: 2

Related Questions