将函数名称作为字符串

时间:2009-10-14 17:14:22

标签: r function

假设我有一堆函数,每个函数都有MyFunction.1等等。我想将这些函数传递给另一个函数,它打印出一个小报告。理想情况下,我希望能够标记报告的各个部分,通过这些部分使用函数来生成结果。

那么有没有什么好方法可以将预定义函数的名称作为字符串?

9 个答案:

答案 0 :(得分:45)

我想要同样的事情,并且记得library(foo)不需要引号,这就是它的作用:

package <- as.character(substitute(package))

答案 1 :(得分:16)

另一种方法是将函数的名称传递给报表函数,然后使用get()命令自行获取函数。例如:

function.names <- c("which","all")
fun1 <- get(function.names[1])
fun2 <- get(function.names[2])

然后在原始字符向量中有名称,并且函数在您定义时具有新名称。在这种情况下,all函数现在被称为fun2

> fun2(c(TRUE, FALSE))
[1] FALSE

或者,如果您真的想保留原始函数名称,只需使用assign函数在本地分配它们:

assign(function.names[2], get(function.names[2]))

如果您现在运行此命令,最终会在all中使用".GlobalEnv"功能。您可以使用ls()来查看此内容。

答案 2 :(得分:7)

这可能会导致parse(eval(...))此时您对此批评持开放态度:

R> library(fortunes)
R> fortune("parse")

If the answer is parse() you should usually rethink the question.
   -- Thomas Lumley
      R-help (February 2005)

R>

那么你的函数必须被称为MyFunction.1等pp?

答案 3 :(得分:6)

您可以通过match.call获取函数的未评估参数。例如:

> x <- function(y) print(match.call()[2])
> x(lm)
lm()

答案 4 :(得分:3)

只想提供一个示例来展示此问题的优势和局限性:

我想用其名称“保存”一个函数,作为另一个函数中使用的选项:

R> foreach(..., .combine=test_fun) {...}

test_fun是函数的名称,当然还有

R> mode(test_fun)  
[1] "function"

当我在foreach中使用它时,我只需要函数名称,而test_fun可以是现有函数(例如cbind)。因此,test_fun

指定
R> test_fun <- get('cbind')

R> test_fun <- assign('cbind', get('cbind'))

所以,你得到了这里的功能

R> test_fun  
function (..., deparse.level = 1)   
.Internal(cbind(deparse.level, ...))  

实际上,原始名称无法维护,因此您无法将test_fun转换回字符串"cbind"

R> deparse(substitute(test_fun))  
[1] "test_fun"

我遗憾地需要解析foreach代码,因此需要字符串中显示的原始名称。这意味着唯一的方法是将'cbind'保存为字符串,并且在这种情况下创建这样的函数对象不会带来任何好处。

答案 5 :(得分:2)

当函数作为对象传递时,它会丢失其名称。例如,参见以下行的结果:

str(lm)
lm

您可以获取函数的参数和正文,但不能获取名称。

我的建议是构建一个命名的函数列表,其名称可以打印出来:

> somefns <- list(lm=lm, aggregate=aggregate)
> str(somefns)
List of 2
 $ lm       :function (formula, data, subset, weights, na.action, method = "qr", 
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, 
    contrasts = NULL, offset, ...)  
 $ aggregate:function (x, ...) 

> somefns[[1]](dist ~ speed, data=cars)

Call:
somefns[[1]](formula = dist ~ speed, data = cars)

Coefficients:
(Intercept)        speed  
     -17.58         3.93  

> names(somefns)[[1]]
[1] "lm"

答案 6 :(得分:2)

怎么样:

deparse(quote(foo.bar))

答案 7 :(得分:0)

@nfultz的观察很不错,因此该线程问题的答案将是:-

workingFunction <- Function(f)
{ functionName <- as.character(substitute(f)) }

workingFunction <- Function(f)
{ functionName <- deparse(substitute(f)) }

所有其他答案将仅返回参数名称本身(在上面的示例中为'f')-我一直在尝试使用它们,因为我一直在研究函数,并遇到了无法检索函数名称的问题在另一个函数内部,其中第一个函数在调用时作为参数传递给第二个函数。希望我的回答对所有可能坚持不变的人有所帮助!

答案 8 :(得分:0)

我在这个问题上也付出了很多努力,不幸的是,给定的解决方案对我来说并不奏效,但是我想出了一种用R6类来命名的方法。

这是一个最小的例子:

NameProvider <-
  R6::R6Class(
    "NameProvider",
    base::list(
      get_fun_name = function(fun_name) { return(fun_name)})
    )

NameUser <-
  R6::R6Class(
    "NameUser",
    base::list(
      do_something = function(fun)
        {
          np <- NameProvider$new()
          fname <- np$get_fun_name(fun_name = base::as.character(base::substitute(fun)))
          do_the_thing <- paste0("THIS IS ", base::toupper(fname), "!!!")
          return(do_the_thing)
        }
        )
      )

nu <- NameUser$new()
nu$do_something(fun = mean) 

NameProvider仅将名称作为字符串返回,并且在类NameUser中调用base::as.character(base::substitute(...))