R:从函数内部在globalenv()中创建一个环境

时间:2011-06-16 17:03:49

标签: r

现在我有了这些话:

envCache <- new.env( hash=TRUE, parent = .GlobalEnv )
print(parent.env(envCache))
R声称环境是在全球环境中,但是当我试图找到环境后,它就不存在了。

我在这里要做的是在全局环境下缓存一些数据帧和环境,所以每次调用一个函数时,它都不必命中服务器再次获取相同的数据。理想情况下,我将在R控制台中使用源命令调用该函数一次,它将获取必要的数据,将其保存到全局环境中的环境中,然后当我从R控制台调用相同的函数时,它将看到它将从中获取数据的环境和数据框,而不是重新查询服务器。

2 个答案:

答案 0 :(得分:8)

当R查找符号时,它会查看当前环境,然后查看环境的父项,依此类推。它尚未将envCache分配到全局环境中。实现你想做的事情的一种方法是创建一个记住状态的'闭包',

makeCache <- function() {
    cache <- new.env(parent=emptyenv())
    list(get = function(key) cache[[key]],
         set = function(key, value) cache[[key]] <- value,
         ## next two added in response to @sunpyg
         load = function(rdaFile) load(rdaFile, cache),
         ls = function() ls(cache))
}

调用makeCache()会返回两个函数getset的列表。

a <- makeCache() 

每个函数都有一个定义它的环境(调用makeCache()时创建的环境)。当您调用a$set("a", 1)时,变量查找规则意味着R首先查找变量cache,首先在函数aCache$set内,并且当它在环境中找不到它时其中set已定义。

> a$get("foo")
NULL
> a$set("foo", 1)
> a$get("foo")
[1] 1

很酷,嗯?请注意,parent=emptyenv())表示不存在的密钥上的get()停止查看cache,否则它将继续查看缓存的父环境,依此类推。

R文档简介中有bank account example非常有趣。为了回应@ sunpyg的评论,我添加了一个loadls函数来添加Rda文件中的数据并列出缓存的内容,例如a$load("foo.Rda")

答案 1 :(得分:5)

这是我提出的替代解决方案。它可能与背景中的其他答案做同样的事情,但代码对我来说更直观。

cacheTesting <- function()
{
    if (exists("cache"))
    { 
        print("IT WORKS!!!") 
        cacheData <- get("test", envir = cache)
        print(cacheData)
    }
    else
    {   
        assign("cache", new.env(hash = TRUE), envir = .GlobalEnv) 
        test <- 42
        assign("test", test, envir = cache) 
    }
}

第一次运行代码使用assign语句在.GlobalEnv中创建环境。第二次运行看到了这个环境,因为它实际上是通过.GlobalEnv,并在打印之前从中提取数据。