rdevtoolsr-packageroxygen2vignette

R Vignette Fails on Internal Package Function


We are adding a vignette to our R package. When documenting the package using roxygen2, the vignette breaks giving the error

Error in tMatrix[i, j, ] <- testVec : 
  number of items to replace is not a multiple of replacement length

However, using devtools::document() or devtools::build_vignettes(), the vignette builds fine.

Minimal example located here.


Solution

  • This is because R sets LC_COLLATE to C when building packages, which is often not the collating sequence of the locale of common operating systems such as those you mentioned in the Github issue yihui/knitr#1719. Because you used sort() in the makeArray() function in your minimal example, and sort() depends on LC_COLLATE, you will get different results in your R console (where LC_COLLATE is often not C) and in R CMD build. To reproduce the error:

    # Copied from https://github.com/GilChrist19/vignetteExample/blob/8973dbc/vignetteExample/R/array.R#L8-L45
    makeArray <- function(names = c("AA", "Aa", "aa")){
    
    
      size <- length(names)
      tMatrix <- array(data=0, dim=c(size, size, size), dimnames=list(names, names, names))
      testVec <- setNames(object = numeric(size), nm = names)
    
      # fill up the array
      for (i in names)
      {
        for (j in names)
        {
    
          j_name <- strsplit(j, split='')[[1]]
          i_name <- strsplit(i, split='')[[1]]
          ij_prod <- as.vector( outer(j_name, i_name, paste0, sep='') )
    
          # sort
          ij_prod <- vapply( strsplit(ij_prod, split=''),
                               function(x) {paste0(sort(x, decreasing=TRUE), collapse='')},
                               FUN.VALUE = character(1))
    
          for (k in ij_prod)
          {
            testVec[k] <- testVec[k]+5
          }
    
          # testVec[] <- testVec/sum(testVec)
    
          tMatrix[i,j, ] <- testVec
    
          testVec[] <- 0
        }
      }
    
    
      return(tMatrix)
    }
    
    
    Sys.setlocale('LC_COLLATE', 'C')
    makeArray()
    

    I'll leave it to you to decide what to do with sort() since I'm not familiar with your function. One hint I could give is that sort(method = 'radix') always follows the C locale, hence is more robust to different locales.