包中的全局变量 - 更推荐哪种方法?

时间:2015-01-31 00:49:32

标签: r packages

我确实理解通常全局变量是邪恶的,我应该避免它们,但如果我的包确实需要一个全局变量,这两种方法中的哪一种更好?还有其他推荐的方法吗?

  1. 使用包可见的环境

    pkgEnv <- new.env()  
    pkgEnv$sessionId <- "xyz123"
    
  2. 使用options

    options("pkgEnv.sessionId" = "xyz123")
    
  3. 我知道有一些其他线程询问如何实现全局变量,但我还没有看到关于推荐哪一个的讨论

2 个答案:

答案 0 :(得分:5)

有些软件包使用隐藏变量(以.开头的变量),例如基数为R的.Random.seed.Last.value。在您的软件包中,您可以这样做

e <- new.env()
assign(".sessionId", "xyz123", envir = e)
ls(e)
# character(0)
ls(e, all = TRUE)
# [1] ".sessionId"

但在您的套餐中,您不需要分配e。您可以使用.onLoad()挂钩在加载包时分配变量。

.onLoad <- function(libname, pkgname) {
    assign(".sessionId", "xyz123", envir = parent.env(environment()))
}

有关包变量的一些好解释,请参阅this question及其答案。

答案 1 :(得分:3)

当大多数人说你应该避免全球性的&#39;变量,它们意味着您不应该分配给全局环境(.GlobalEnvGlobalEnvas.environment(1)),或者您不应该通过除传递此类数据之外的任何方法在内部函数之间传递信息作为函数调用的参数。

缓存完全是另一回事。我经常缓存我不想重新计算(memoization)或重新查询的结果。我在包中使用了很多的模式如下:

myFunction <- local({

    cache <- list() # or numeric(0) or whatever

    function(x,y,z){ 

        # calculate the index of the answer 
        # (most of the time this is a trivial calculation, often the identity function)
        indx = answerIndex(x,y,z)

        # check if the answer is stored in the cache
        if(indx %in% names(cacheList))
            # if so, return the answer
            return(cacheList[indx])

        [otherwise, do lots of calculations or data queries]

        # store the answer
        cahceList[indx] <<- answer

        return(answer)
    }

})

local的调用创建了一个新环境,我可以使用作用域赋值运算符<<-存储结果,而不必担心包已经密封的事实,以及最后一个表达式(函数定义)作为调用local()的值返回,并绑定到名称myFunction