R中包中的全局变量

bsk*_*ard 48 r global-variables

我正在用R开发一个包.我有一堆函数,其中一些需要一些全局变量.如何管理包中的全局变量?

我已经阅读了一些关于环境的内容,但我不明白它是如何工作的,如果这就是解决问题的方法.

Gre*_*now 54

您可以在环境中使用包本地变量.这些变量可用于包中的多个功能,但不能(轻松)访问用户,并且不会干扰用户工作空间.一个简单快速的例子是:

pkg.env <- new.env()

pkg.env$cur.val <- 0
pkg.env$times.changed <- 0

inc <- function(by=1) {
    pkg.env$times.changed <- pkg.env$times.changed + 1
    pkg.env$cur.val <- pkg.env$cur.val + by
    pkg.env$cur.val
}

dec <- function(by=1) {
    pkg.env$times.changed <- pkg.env$times.changed + 1
    pkg.env$cur.val <- pkg.env$cur.val - by
    pkg.env$cur.val
}

cur <- function(){
    cat('the current value is', pkg.env$cur.val, 'and it has been changed', 
        pkg.env$times.changed, 'times\n')
}

inc()
inc()
inc(5)
dec()
dec(2)
inc()
cur()
Run Code Online (Sandbox Code Playgroud)

  • 这是一个有用的实践,我要补充一点,作为一个安全措施,当创建环境作为变量容器时,通常应该将父环境设置为`emptyenv()`,以防止意外地在搜索中获取更高的值path:因此`new.env(parent = emptyenv())`,而不仅仅是`new.env()`. (15认同)
  • 另一个附录-您可能需要执行`assign('key',value,pkg.env)`,而不是`R'的最新版本中的`pkg.env $ key &lt;-value`,因为`pkg.env`通常是锁定的环境。 (2认同)

Jam*_*mes 17

你可以设置一个option,例如

options("mypkg-myval"=3)
1+getOption("mypkg-myval")
[1] 4
Run Code Online (Sandbox Code Playgroud)

  • 这究竟会存储在哪里? (2认同)

Pau*_*tra 10

通常,全局变量是邪恶的.它们为邪恶的根本原则是您希望最小化包中的互连.这些互连通常会导致函数产生副作用,即它不仅取决于输入参数的结果,还取决于某些全局变量的值.特别是当函数数量增加时,这很难得到正确的调试.

对于R中的全局变量,请参阅此SO帖子.

编辑以回应您的评论: 另一种方法是将所需信息传递给需要它的函数.您可以创建一个包含此信息的新对象:

token_information = list(token1 = "087091287129387",
                         token2 = "UA2329723")
Run Code Online (Sandbox Code Playgroud)

并要求所有需要此信息的函数将其作为参数:

do_stuff = function(arg1, arg2, token)
do_stuff(arg1, arg2, token = token_information)
Run Code Online (Sandbox Code Playgroud)

通过这种方式,从代码中可以清楚地看到函数中需要令牌信息,您可以自己调试该函数.此外,该函数没有副作用,因为它的行为完全由其输入参数决定.典型的用户脚本如下所示:

token_info = create_token(token1, token2)
do_stuff(arg1, arg2, token_info)
Run Code Online (Sandbox Code Playgroud)

我希望这会让事情更清楚.

  • 我认为你为什么全局变量是邪恶的论证需要对R进行一些调整 - 你在包中创建的所有函数都是全局变量.他们是邪恶的吗?;) (10认同)
  • 正常的R模式是拥有某种"句柄"对象来保存你的标记,并将该句柄传递给你的函数.这也允许您使用不同的令牌进行多个并发会话.例如,这就是数据库访问的模式. (6认同)
  • 谢谢你的回答.我有编程经验,并且知道全局变量通常是nogo.但是,我正在建立对服务的API访问,为了保持与此服务的连接,这些功能需要几个令牌.这些令牌应该是所有功能都可以访问的,我提出的是创建一个存储这些数据的.RData文件,但这似乎是一个糟糕的想法. (3认同)