How to list all the functions signatures in an R file?

前端 未结 2 669
时光取名叫无心
时光取名叫无心 2020-12-10 20:40

Is there an R function that lists all the functions in an R script file along with their arguments?

i.e. an output of the form:

func1(var1, var2)
fu         


        
相关标签:
2条回答
  • 2020-12-10 20:45

    Using [sys.]source has the very undesirable side-effect of executing the source inside the file. At the worst this has security problems, but even “benign” code may simply have unintended side-effects when executed. At best it just takes unnecessary time (and potentially a lot).

    It’s actually unnecessary to execute the code, though: it is enough to parse it, and then do some syntactical analysis.

    The actual code is trivial:

    file_parsed = parse(filename)
    functions = Filter(is_function, file_parsed)
    function_names = unlist(Map(function_name, functions))
    

    And there you go, function_names contains a vector of function names. Extending this to also list the function arguments is left as an exercise to the reader. Hint: there are two approaches. One is to eval the function definition (now that we know it’s a function definition, this is safe); the other is to cheat and just get the list of arguments to the function call.

    The implementation of the functions used above is also not particularly hard. There’s probably even something already in R core packages (utils has a lot of stuff) but since I’m not very familiar with this, I’ve just written them myself:

    is_function = function (expr) {
        if (! is_assign(expr))
            return(FALSE)
        value = expr[[3]]
        is.call(value) && as.character(value[[1]]) == 'function'
    }
    
    function_name = function (expr)
        as.character(expr[[2]])
    
    is_assign = function (expr)
        is.call(expr) && as.character(expr[[1]]) %in% c('=', '<-', 'assign')
    

    This correctly recognises function declarations of the forms

    1. f = function (…) …
    2. f <- function (…) …
    3. assign('f', function (…) …)

    It won’t work for more complex code, since assignments can be arbitrarily complex and in general are only resolvable by actually executing the code. However, the three forms above probably account for ≫ 99% of all named function definitions in practice.

    0 讨论(0)
  • 2020-12-10 20:59

    UPDATE: Please refer to the answer by @Konrad Rudolph instead

    You can create a new environment, source your file in that environment and then list the functions in it using lsf.str() e.g.

    test.env <- new.env()
    sys.source("myfile.R", envir = test.env)
    lsf.str(envir=test.env)
    rm(test.env)
    

    or if you want to wrap it as a function:

    listFunctions <- function(filename) {
      temp.env <- new.env()
      sys.source(filename, envir = temp.env)
      functions <- lsf.str(envir=temp.env)
      rm(temp.env)
      return(functions)
    }
    
    0 讨论(0)
提交回复
热议问题