4

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.

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
Sowmya S. Manian
  • 3,723
  • 3
  • 18
  • 30
  • 1
    I imagine one would have to use string matching to do such a task (`grep`). e.g. `select %>% body() %>% toString()`. You are also going to want a list of the functions you are searching for. – zacdav Sep 13 '16 at 07:24
  • 1
    Possible duplicate of [Finding out which functions are called within a given function](http://stackoverflow.com/questions/11872879/finding-out-which-functions-are-called-within-a-given-function) – 989 Sep 13 '16 at 09:11

5 Answers5

7

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.

Rich Scriven
  • 97,041
  • 11
  • 181
  • 245
5

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"
Rorschach
  • 31,301
  • 5
  • 78
  • 129
2

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.

zacdav
  • 4,603
  • 2
  • 16
  • 37
1

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"
cccmir
  • 953
  • 6
  • 12
0
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.

Ferdi
  • 540
  • 3
  • 12
  • 23
  • `gsub` is not working in your answer. I have edited my `grep` part now I am getting the output posted above. Just need to print text before `(` also, if any function is repeating I do not want them to be repeated in the output. – Sowmya S. Manian Sep 13 '16 at 07:34
  • the gsub is not working. Dont know why. I tried thrice. May be tehre is some problem in the pattern you provided to gsub? – Sowmya S. Manian Sep 13 '16 at 08:04
  • On my console (RStudio, R 3.3.0) gsub is working. However if I implement some minor changes such as `(` instead of `)` i get the following error **Error in gsub("(.*$", "", as.list(Fun1)[3]) : invalid regular expression '(.*$', reason 'Missing ')''** – Ferdi Sep 13 '16 at 08:08