2009-10-14 93 views
41

说我有一堆函数,每个都有类似MyFunction.1等。我想将这些函数传递给另一个函数,该函数打印出一个小报告。理想情况下,我希望能够标记使用哪个函数生成结果的报告部分。获取函数名称作为字符串

那么有没有什么好的方法来获取预定义函数的名称作为一个字符串?

回答

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?

+0

哈 - 我害怕我会得到那笔财富。我只想要能够像compare.distribution.methods(c(two.choice,go.left,simple.random.sample))那样调用函数,并获取矢量中每个方法的结果表。如果这不是R的一部分,那么我们就可以使用这个名字来创建一个标签,那么这个问题得到回答就更好了 – HamiltonUlmer 2009-10-14 17:26:48

+1

S3方法调度为你做了!不要害怕“OO”,这将是一个很好的简单例子,开始使用它。并温柔的文档指向你...也许钱伯斯去年的“数据分析软件”书? – 2009-10-14 17:49:43

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" 
+0

两个不错的选择[刚刚发布在这里](http://stackoverflow.com/questions/25621108/keeping功能-names-when-stored-in-an-object) – 2014-09-02 11:54:40

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(function.names[2], get(function.names[2])) 

如果你现在运行这个命令,你的函数将会在".GlobalEnv"中生效。你可以用ls()来看这个。

+1

这不是真的作者的问题,是一个不太好的w orkaround。请参阅下面的match.call(fun)[2]。 – Dennis 2013-07-26 13:37:27

7

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

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

的确如此,不过这里有帮助。如果你说“z < - lm”,然后x(z)你得到“z”,而不是“lm”。 – Harlan 2009-10-14 18:43:29

+0

没错,虽然目前还不清楚什么是正确的行为。哪个功能是“规范”,应该打印? – 2009-10-15 00:15:14

+0

在功能语言中,函数的名称并不重要。您可以轻松地重命名函数,或者拥有无名称的函数。 match.call函数只是给出了被调用时保存该函数的变量的名称,所以从这个意义上说,它正在做它唯一可以做的事情。我不知道“规范”真的进入了它...... – Harlan 2009-10-15 02:13:41

1

你看这个:

deparse(quote(foo.bar)) 
40

我想同样的事情,并记住library(foo)并不需要引号,这是它做什么:

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

好观察! objectName = as.character(quote(object))也适用 – RockScience 2011-07-13 08:58:06

+0

好戏,谢谢。 – tunnuz 2013-07-08 07:34:39

+0

如何显示'lbrary'的代码? – 2016-04-21 10:58:45

2

只是想举一个例子来说明这个问题的优点和局限性:

我想,“拯救”的功能与它的名字,因为这将在另一个函数中使用的选项:

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" 

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