【问题标题】:Keeping function names when stored in an object存储在对象中时保留函数名称
【发布时间】:2014-09-02 10:22:25
【问题描述】:

我正在准备一个包,用户必须将函数及其相关参数存储在list 中以供以后使用。这是其工作原理的典型示例:

准备包含函数名和参数的列表

parameters <- list(a1 = list(fun = dnorm,
                             args = list(mean = 150, sd = 100)),
                   a2 = list(fun = dpois,
                             args = list(lambda = 40)))

下面是这个参数对象如何在其他函数中使用的示例:

x <- 1:100
myfunction <- function(x, var, parameters)
{
    results <- list(var = var,
                    y = do.call(parameters[[var]]$fun, 
                                c(list(x), parameters[[var]]$args)),
                    parameters = parameters)
    class(results) <- "customclass"
    return(results)
}
myfunction(x, "a1", parameters)

现在假设我想在myfunction 的输出中打印存储在parameters 中的函数的名称。

print.customclass <- function(X)
{
   cat("Function name:", X$parameters[[X$var]]$fun)
}

此自定义打印不起作用:

> myfunction(x, "a1", parameters)
Error in cat(list(...), file, sep, fill, labels, append) : 
argument 2 (type 'closure') cannot be handled by 'cat' 

我还尝试了其他地方找到的其他建议解决方案,例如:

print.customclass <- function(X)
{
   cat("Function name:", deparse(quote(X$parameters[[X$var]]$fun)))
}

> myfunction(x, "a1", parameters)
Function name: X$parameters[[X$var]]$fun

根据Harlan in this other question,当存储在另一个R对象中时,函数的名称会丢失。他建议用函数名来命名函数列表,例如:

parameters <- list(a1 = list(dnorm = dnorm,
                             args  = list(mean = 150, sd = 100)),
                   a2 = list(dpois = dpois,
                             args  = list(lambda = 40)))

但是,我想为 list 的每个元素保留相同的名称 (fun)。

因此我的问题是

当函数存储在另一个对象中时,任何人都可以想出一种方法来保留函数名称吗?

非常感谢您的帮助!

【问题讨论】:

    标签: r


    【解决方案1】:

    你可以使用alists:

    parameters <- list(a1 = alist(fun = dnorm,
                                 args = list(mean = 150, sd = 100)),
                       a2 = alist(fun = dpois,
                                 args = list(lambda = 40)))
    #probably better to write a constructor method for parameters objects
    
    
    x <- 1:100
    myfunction <- function(x, var, parameters)
    { f <- function(x) do.call(fun, c(list(x), args))
      formals(f) <- c(formals(f), parameters[[var]]) 
      results <- list(var = var,
                      y = f(x),
                      parameters = parameters)
      class(results) <- "customclass"
      return(results)
    }
    
    print.customclass <- function(X)
    {
      cat("Function name:", X$parameters[[X$var]]$fun)
    }
    
    myfunction(x, "a1", parameters)
    #Function name: dnorm
    

    【讨论】:

    • 这是一个很好的答案,我不知道alist。你是对的,我应该为参数对象写一个构造方法。我还不确定如何编写它以使其非常用户友好。
    • @BorisLeroy 自从evaling 之后,我已经稍微改变了函数,看起来有点笨重。
    【解决方案2】:

    我建议使用函数名称而不是函数本身来定义您的 parameters 参数,并在 myfunctionmatch.fun 的主体中检索函数:

        parameters <- list(a1 = list(fun = "dnorm",
                             args = list(mean = 150, sd = 100)),
                   a2 = list(fun = "dpois",
                             args = list(lambda = 40)))
    
        myfunction <- function(x, var, parameters)
        {
            results <- list(var = var,
                    y = do.call(match.fun(parameters[[var]]$fun), 
                                c(list(x), parameters[[var]]$args)),
                    parameters = parameters)
            class(results) <- "customclass"
            return(results)
        }
    

    【讨论】:

    • 这是另一个不错的答案,与@Roland 的答案一样有效。我还没有决定要实施哪一个,但对我来说两者都非常有效。