Sowmya S. Manian
Sowmya S. Manian

Reputation: 3843

How to get the list of in-built functions used within a function

Lets say I have a function named Fun1 within which I am using many different in-built functions of R for different different processes. Then how can I get a list of in-built functions used inside this function Fun1

  Fun1 <- function(x,y){
  sum(x,y)
  mean(x,y)
  c(x,y)
  print(x)
  print(y)
  }

So My output should be like list of characters i.e. sum, mean, c, print. Because these are the in-built functions I have used inside function Fun1.

I have tried using grep function

 grep("\\(",body(Fun1),value=TRUE)
 # [1] "sum(x, y)"  "mean(x, y)" "c(x, y)"    "print(x)"   "print(y)" 

It looks ok, but arguments should not come i.e. x and y. Just the list of function names used inside body of function Fun1 here.

So my overall goal is to print the unique list of in-built functions or any create functions inside a particular function, here Fun1.

Any help on this is highly appreciated. Thanks.

Upvotes: 4

Views: 729

Answers (5)

Rich Scriven
Rich Scriven

Reputation: 99371

You could use all.vars() to get all the variable names (including functions) that appear inside the body of Fun1, then compare that with some prepared list of functions. You mention in-built functions, so I will compare it with the base package object names.

## full list of variable names inside the function body
(vars <- all.vars(body(Fun1)[-1], functions = TRUE))
# [1] "sum"   "x"     "y"     "mean"  "c"     "print"

## compare it with the base package object names
intersect(vars, ls(baseenv()))
# [1] "sum"   "mean"  "c"     "print"

I removed the first element of the function body because presumably you don't care about {, which would have been matched against the base package list.

Another possibility, albeit a bit less reliable, would be to compare the formal arguments of Fun1 to all the variable names in the function. Like I said, likely less reliable though because if you make assignments inside the function you will end up with incorrect results.

setdiff(vars, names(formals(Fun1)))
# [1] "sum"   "mean"  "c"     "print"

These are fun though, and you can fiddle around with them.

Upvotes: 7

Rorschach
Rorschach

Reputation: 32466

Access to the parser tokens is available with functions from utils.

tokens <- utils::getParseData(parse(text=deparse(body(Fun1))))
unique(tokens[tokens[["token"]] == "SYMBOL_FUNCTION_CALL", "text"])
[1] "sum"   "mean"  "c"     "print"

Upvotes: 5

zacdav
zacdav

Reputation: 4671

This should be somewhat helpful - this will return all functions however.

func_list = Fun1 %>% 
  body() %>% # extracts function
  toString() %>% # converts to single string
  gsub("[{}]", "", .)  %>% # removes curly braces
  gsub("\\s*\\([^\\)]+\\)", "", .) %>% # removes all contents between brackets
  strsplit(",") %>% # splits strings at commas
  unlist() %>% # converts to vector
  trimws(., "both") # removes all white spaces before and after`

[1] "" "sum" "mean" "c" "print" "print"

> table(func_list)
func_list
          c  mean print   sum 
    1     1     1     2     1 

This is extremely limited to your example... you could modify this to be more robust. It will fall over where a function has brackets nesting other functions etc.

Upvotes: 2

cccmir
cccmir

Reputation: 1003

this is not so beautiful but working:

Fun1 <- function(x,y){
    sum(x,y)
    mean(x,y)
    c(x,y)
    print(x)
    print(y)
}


getFNamesInFunction <- function(f.name){
    f <- deparse(body(get(f.name)))
    f <- f[grepl(pattern = "\\(", x = f)]
    f <- sapply(X = strsplit(split = "\\(", x = f), FUN = function(x) x[1])
    unique(trimws(f[f != ""]))
}
getFNamesInFunction("Fun1")
[1] "sum"   "mean"  "c"     "print"

Upvotes: 1

Ferdi
Ferdi

Reputation: 560

as.list(Fun1)[3]

gives you the part of the function between the curly braces.

{
    sum(x, y)
    mean(x, y)
    c(x, y)
    print(x)
    print(y)
}

Hence

 gsub( ").*$", "", as.list(Fun1)[3])

gives you everything before the first " ) " appears which is presumable the name of the first function.

Taking this as a starting point you should be able to include a loop which gives you the other functions and not the first only the first one.

Upvotes: 0

Related Questions