现在我有了这些话:
envCache <- new.env( hash=TRUE, parent = .GlobalEnv )
print(parent.env(envCache))
R声称环境是在全球环境中,但是当我试图找到环境后,它就不存在了。
我在这里要做的是在全局环境下缓存一些数据帧和环境,所以每次调用一个函数时,它都不必命中服务器再次获取相同的数据。理想情况下,我将在R控制台中使用源命令调用该函数一次,它将获取必要的数据,将其保存到全局环境中的环境中,然后当我从R控制台调用相同的函数时,它将看到它将从中获取数据的环境和数据框,而不是重新查询服务器。
答案 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()
会返回两个函数get
和set
的列表。
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的评论,我添加了一个load
和ls
函数来添加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,并在打印之前从中提取数据。