我有一个计数器功能,我喜欢包围另一个功能("有趣"),以帮助记录我称之为多少次。我通过创建一个新环境来跟踪呼叫" counter.env"如果它还没有存在并将计数存储在那里。
counter <- function(fun) {
if (!exists("counter.env", envir = .GlobalEnv)) {
counter.env <<- new.env(parent = globalenv())
assign("i", 0, envir = counter.env)
}
function(...) {
local(i <- i+1, env = counter.env)
fun(...)
}
}
我也有一个功能&#34; get_calls&#34;这只是一个从环境中获取计数的调用。如果用户在他们正在调用的实际功能之前调用它,我会喜欢运行0,无论他们为什么这样做。
get_calls <- function() {
if (!exists("counter.env", envir = .GlobalEnv)) {
counter.env <<- new.env(parent = .GlobalEnv)
assign("i", 0, envir = counter.env)
}
get("i", envir = counter.env)
}
最后让我们说我的包装功能是一个带有自己参数的函数,&#34; fun(arg1)&#34;。所以我把它包起来。
count.and.call <- counter(fun)
我称之为:
count.and.call(arg1)
立即&#34; counter.env&#34;在我的全局环境中创建,我可以使用get_calls返回调用。
现在,鼓声当我将这些功能放在一个包中,然后我构建包,然后运行
count.and.call(arg1)
counter.env不是在全局环境中创建的。并显示
error in eval(quote(i <- i + 1), counter.env) :
object 'counter.env' not found
我最关心的是修复我的计数器,这可能与环境范围有关。
但是我也不确定我是否使用了我的计数器功能的最佳实践,如果是的话,我可以得到一些建议吗?
答案 0 :(得分:2)
最佳做法是您的软件包不应干涉全局环境。如果要存储状态,请在包的命名空间中为其创建环境。您甚至不必自己指定位置,默认情况下会自动发生。
在源文件中:
counter.env <- new.env()
# this gets run every time your package is loaded
.onLoad <- function(libname, pkgname)
{
counter.env$i <- 0
}
counter <- function(fun)
{
# do stuff...
counter.env$i <- counter.env$i + 1
}
reset_counter <- function()
{
counter.env$i <- 0
}
# necessary if you want the user to see the counter and you don't export counter.env
get_counter <- function()
{
counter.env$i
}
答案 1 :(得分:2)
另一种非常R-ish方式的方法是使用闭包。例如:
countingFun <- function(fun) {
count <- 0
function(x) {
count <<- count + 1
fun(x)
}
}
count <- function(fun) {
environment(fun)$count
}
这会将计数保留在函数的环境中,该函数是自动创建的,包含调用countingFun
的本地变量。然后就可以了
myMean <- countingFun(mean)
mySd <- countingFun(sd)
myMean(x)
mySd(x)
myMean(x)
count(myMean) # 2
count(mySd) # 1
您可能希望向count
添加一些错误检查,以确保不会对未被计算的函数调用。