Barbara
Barbara

Reputation: 347

CMD check errors

I am trying to create a package for the first time and am having trouble with R CMD check.

Initially, I was getting "notes" saying that there was no visible binding for my global variables. I added assignments to those variables at the top of the file being checked and now when the examples run, I get errors saying that I cannot change the value of a locked binding. Since I am not locking the bindings, I assume this is something that R CMD check is doing, but I have been unable to find any documentation describing what this means or how to fix it.

Here is a specific example. My R file includes a function like this:

.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)
}

With the function defined like this, I would get the note:

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

To resolve this, I added above the definition of .ddg.init.tables:

ddg.proc.nodes <- NULL

The note went away, but later in the R CMD check process when checking the examples, while running the line from the example:

ddg.init()

I now get the error:

> 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

If I leave out the initialization, I get the note, but the example executes.

What is the meaning of the "locked binding" message and what is the best way to fix it?

Thanks for your help.

Upvotes: 3

Views: 386

Answers (1)

Martin Morgan
Martin Morgan

Reputation: 46886

Symbols (functions or variables) in your package are defined in the so-called 'name space' of your package. Roughly, when your R package is 'load'ed, R creates an environment and populates it with the symbols defined in your package. It then 'locks' the environment so that your package symbols cannot be accidentally re-defined (e.g., so the user can't accidentally change the definition of one of your functions). R might then optionally 'attach' the locked environment to the search() path, and voila, the user has access to your amazing functionality.

A side-effect of locking your environment to protect your functions from the user making accidental changes is that the package code cannot itself change symbol definitions. Usually this is a good thing -- you want the package code to perform consistently.

Your use case seems to be about creating an object at 'run time'. It is usually sufficient to do this after the environment has been created but before it is locked, and this is available by writing a .onLoad function (see ?.onLoad) in your package, more-or-less traditionally placed in a file zzz.R. You would then invoke ddg.init() while the name space could still be written.

A different scenario is that the structure of the objects are determined you wrote the function. In this case one would create an R object and include it in the package directly, either in R/sysdata.rda or in the data/ folder, typically with 'lazy loading' allowing the symbols defined in the object to be referenced by your R code as though they were defined in the package.

A third possibility is that you need to create the objects at run-time, during an interactive session, e.g., recording whether a web service is available at the time the user executes a function. For this the idea is to create an environment in your name space

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

and to modify the content of the environment

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

Although you can't change the value of .cache (because it's locked, e.g., you couldn't change .cache from an environment to a list, or to a new environment) you can modify the contents of the environment that you've already allocated.

Upvotes: 2

Related Questions