r - 找出给定函数中调用了哪些函数

标签 r function recursion dependencies function-declaration

Possible Duplicate:
Generating a Call Graph in R

I'd like to systematically analyze a given function to find out which other functions are called within that very function. If possible, recursively.

I came across this function in a blog post by milktrader,我可以对(或 namespace )执行类似的操作

listFunctions <- function(
    name,
    ...
){ 
    name.0  <- name
    name    <- paste("package", ":", name, sep="")
    if (!name %in% search()) {
        stop(paste("Invalid namespace: '", name.0, "'"))
    }
    # KEEP AS REFERENCE       
#    out <- ls(name)
    funlist <- lsf.str(name)
    out     <- head(funlist, n=length(funlist))
    return(out)
}

> listFunctions("stats")
  [1] "acf"                  "acf2AR"               "add.scope"           
  [4] "add1"                 "addmargins"           "aggregate"           
  [7] "aggregate.data.frame" "aggregate.default"    "aggregate.ts"        
 [10] "AIC"                  "alias"                "anova"               
....
[499] "xtabs"   

但是,我想要一个函数,其中name是函数的名称,返回值是name中调用的函数的字符向量(或者列表,如果递归完成的话)。

动机

我实际上需要某种基于字符的输出(矢量或列表)。这样做的原因是,我正在使用通用包装函数来并行化任意“内部函数”,在该函数中,您不必经过费时的反复试验即可找出哪些其他函数。内部功能取决于。因此,我需要的函数的输出将直接在snowfall::sfExport()和/或snowfall::sfSouce中使用。

编辑2012-08-08

由于存在重复性,因此出现了一些投票否决的情况,明天我将检查如何将答案与另一个问题合并。

最佳答案

必须有更好的方法,但这是我的尝试:

listFunctions <- function(function.name, recursive = FALSE, 
                          checked.functions = NULL){

    # Get the function's code:
    function.code <- deparse(get(function.name))

    # break code up into sections preceding left brackets:
    left.brackets <- c(unlist(strsplit(function.code, 
                                       split="[[:space:]]*\\(")))

    called.functions <- unique(c(unlist(sapply(left.brackets, 
                                               function (x) {

        # Split up according to anything that can't be in a function name.
        # split = not alphanumeric, not '_', and not '.'
        words <- c(unlist(strsplit(x, split="[^[:alnum:]_.]")))

        last.word <- tail(words, 1)
        last.word.is.function <- tryCatch(is.function(get(last.word)),
                                      error=function(e) return(FALSE))
        return(last.word[last.word.is.function])
    }))))

    if (recursive){

        # checked.functions: We need to keep track of which functions 
        # we've checked to avoid infinite loops.
        functs.to.check <- called.functions[!(called.functions %in%
                                          checked.functions)]

        called.functions <- unique(c(called.functions,
            do.call(c, lapply(functs.to.check, function(x) {
                listFunctions(x, recursive = T,
                              checked.functions = c(checked.functions,          
                                                    called.functions))
                }))))
    }
    return(called.functions)
}

结果:
> listFunctions("listFunctions", recursive = FALSE)
 [1] "function"      "deparse"       "get"           "c"            
 [5] "unlist"        "strsplit"      "unique"        "sapply"       
 [9] "tail"          "tryCatch"      "is.function"   "return"       
[13] "if"            "do.call"       "lapply"        "listFunctions"

> system.time(all.functions <- listFunctions("listFunctions", recursive = TRUE))
   user  system elapsed 
  92.31    0.08   93.49 

> length(all.functions)
  [1] 518

如您所见,递归版本返回许多函数。这样做的问题是,它会在过程中调用的每个函数都返回,这显然随着您的执行而累加。无论如何,我希望您可以使用它(或对其进行修改)以满足您的需求。

关于r - 找出给定函数中调用了哪些函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11872879/

相关文章:

r - 将 R 脚本编译成独立的 .exe 文件?

r - 如何在ifelse中包含NA?

c++ - 为什么 std::bind 在这个例子(成员函数)中没有占位符就不能工作?

function - 在定义之前在 Swift 中声明一个函数

algorithm - 将返回 2 次递归的递归函数转换为迭代

r - 从数据表中分离变量并创建新的数据表

javascript - 以编程方式向 Javascript 中的对象添加属性

c++ - 输入/输出文件(数独求解器)

c++ - C++ 中的 Cracker Barrel Puzzle 解算器

r - 优雅的索引到向量/矩阵的末尾