【问题标题】:CMD check errorsCMD 检查错误
【发布时间】:2014-06-08 20:28:59
【问题描述】:

我是第一次尝试创建一个包,但遇到了 R CMD 检查问题。

最初,我收到“注释”,说我的全局变量没有可见的绑定。一世 在被检查的文件顶部添加了对这些变量的赋值,现在当示例运行时,我收到错误消息,说我无法更改锁定绑定的值。由于我没有锁定绑定,我认为这是 R CMD 检查正在做的事情,但我找不到任何描述这意味着什么或如何修复它的文档。

这是一个具体的例子。我的 R 文件包含这样的函数:

.ddg.init.tables <- function() {
    size <- 100
    ddg.proc.nodes <<- data.frame(ddg.type = character(size),
        ddg.num = numeric(size), ddg.name = character(size),
        ddg.value = character(size), stringsAsFactors=FALSE)
}

使用这样定义的函数,我会得到注释:

.ddg.init.tables: no visible binding for '<<-' assignment to 'ddg.proc.nodes'

为了解决这个问题,我在上面添加了 .ddg.init.tables 的定义:

ddg.proc.nodes <- NULL

注释消失了,但后来在检查示例时的 R CMD 检查过程中,同时运行示例中的行:

ddg.init()

我现在得到错误:

> ddg.init()
Error in .ddg.init.tables() : 
  cannot change value of locked binding for 'ddg.proc.nodes'
Calls: ddg.init -> .ddg.init.tables
Execution halted

如果我省略初始化,我会得到注释,但示例会执行。

“锁定绑定”消息的含义是什么?修复它的最佳方法是什么?

感谢您的帮助。

【问题讨论】:

    标签: r


    【解决方案1】:

    包中的符号(函数或变量)在包的所谓“名称空间”中定义。粗略地说,当你的 R 包被“加载”时,R 会创建一个环境并用你的包中定义的符号填充它。然后它会“锁定”环境,这样您的包符号就不会被意外重新定义(例如,用户不会意外更改您的某个函数的定义)。然后 R 可以选择将锁定的环境“附加”到 search() 路径,瞧,用户可以访问您的惊人功能。

    锁定环境以保护函数免受用户意外更改的副作用是包代码本身不能更改符号定义。通常这是一件好事——您希望包代码能够始终如一地执行。

    您的用例似乎是关于在“运行时”创建一个对象。在创建环境之后但在它被锁定之前执行此操作通常就足够了,这可以通过在包中编写.onLoad 函数(参见?.onLoad)来获得,或多或少传统上放置在文件中zzz.R.然后,您将调用 ddg.init(),同时仍然可以写入名称空间。

    另一种情况是对象的结构由您编写的函数确定。在这种情况下,可以创建一个 R 对象并将其直接包含在包中,无论是在 R/sysdata.rda 还是在 data/ 文件夹中,通常使用“延迟加载”,允许您的 R 引用对象中定义的符号代码就好像它们是在包中定义的一样。

    第三种可能性是您需要在运行时,在交互式会话期间创建对象,例如,在用户执行功能时记录 Web 服务是否可用。为此,我们的想法是在您的名称空间中创建一个环境

    .cache <- new.env(parent=emptyenv())
    

    以及修改环境的内容

    setIsUp <- function() {
        .cache[["isup"]] <- TRUE
    }
    

    虽然您无法更改 .cache 的值(因为它已被锁定,例如,您无法将 .cache 从环境更改为列表或新环境),但您可以修改环境的内容你已经分配好了。

    【讨论】:

    • 感谢您提供如此详细的评论。这是非常有帮助的。只是为了确保我理解,在初始化后我想更改其绑定的任何变量是否需要存储在环境中,使用 getter 和修饰符函数来访问和更新它们,如上面的第三种可能性所示?
    • @Barbara 是的,您应该将具有更改绑定的变量放入环境中。使用“包全局”变量并不常见,也不是特别好的编程习惯,因为它具有“远距离作用”——一个函数在星期二以一种方式工作,但在星期四不同(因为包全局变量已经改变),并且“用户”很困惑——所以你可能会仔细考虑这些是否合适。另一种方法是向函数添加具有默认值的参数。有时,例如缓存昂贵的计算,包全局变量是合适的。
    猜你喜欢
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2016-01-13
    • 2017-09-13
    相关资源
    最近更新 更多