1) Useful functions when developing R packages
a) devtools::spell_check
devtools::spell_check
DESCRIPTION does not contain 'Language' field. Defaulting to 'en-US'.
focussing window-functions.Rmd:89
invokation NEWS.md:787
I think it's important to care also about these little details...
b) codetools::checkUsagePackage
library(mypackage)
codetools::checkUsagePackage(pack = "mypackage")
#......
afunction: no visible global function definition for (/home/aa/software/R/dplyr/R/compat-dbplyr.R:57)
anotherfunction: local variable ‘xx’ assigned but may not be used
#.......
Note: you can get some of this information also by running code diagnostics in RStudio (Code -> Code diagnostics).
There are situations where it gives false positives (if you use glue), but despite this I find it very useful.
c) goodpractice::gp
https://github.com/MangoTheCat/goodpractice
goodpractice::gp()
It is good practice to
✖ use '<-' for assignment instead of '='. '<-' is the standard, and R users and developers are used it
and it is easier to read your code for them if you use '<-'.
✖ avoid long code lines, it is bad for readability. Also, many people prefer editor windows that are
about 80 characters wide. Try make your lines shorter than 80 characters
✖ omit trailing semicolons from code lines. They are not needed and most R coding standards forbid them
✖ avoid sapply(), it is not type safe. It might return a vector, or a list, depending on the input data.
Consider using vapply() instead.
✖ avoid 1:length(...), 1:nrow(...), 1:ncol(...), 1:NROW(...) and 1:NCOL(...) expressions. They are error
prone and result 1:0 if the expression on the right hand side is zero. Use seq_len() or seq_along() instead.
✖ not import packages as a whole, as this can cause name clashes between the imported packages. Instead,
import only the specific functions you need.
2) Troubleshooting: data.table not working in a package
If you use data.table in your package, the recommendation is to import it. I usually have a file called <packagename.R> which looks like this:
#' packagename: some description
#'
#' @docType package
#' @name packagename
#'
#' @import data.table
#' @noRd
NULL
Then I use roxygen to create the documentation.
Important: make sure you have at least one R statement in the that file, otherwise roxygen2 won't build the documentation. You can easily check this by looking at the generated NAMESPACE file. If you find there the line
import(data.table)
you are safe. Otherwise, data.table will not be imported. The consequences are very strange: data.table operators and functions will not work in your package,
each data.table will be treated as a data.frame. To avoid this, make sure sure you have an R statement in your <packagename.R>. The simplest solution is just to include the NULL statement.
3) Debugging R packages
I like the package debugme. It's lightweight and I can switch the debugging via an environment variable, so no need to rebuild the package. In addition, I can also see debug statements for functions running on parallel clusters via foreach.
On same rare occasions I got roxygen2 errors while loading debugme in .onLoad:
Error in .f(.x[[i]], ...) : R6 class without source references
The solution, as indicated here is to switch off the special treatment of R6 classes by including the following line in DESCRIPTION:
Roxygen: list(r6 = FALSE)
I agree, this is not the optimal solution, I just don't have something better in the moment...
4) Advice on writing functions
Here some of my pet-peeves:
- do not write functions which end with the following line and have no other return statement:
return(NULL)
And no, there was no if/else before this...
- do not write functions which end with the following line:
return(TRUE)
and no return(FALSE) nowhere in the function body
- pay attention to constructs like these:
# don't do this
if (x > 0) {
y <- 42/x
} else {
y <- 0
}
# do this
if (x > 0) {
# some code
return(x)
}
if (x == -1) {
# other lines of code
return(NA_real_)
}
return(NULL)
# don't do this
if (x > 42) {
return(TRUE)
}
return(FALSE)
# do this
return(x > 42)
Final words: I know a little story about a little girl, who everytime she visited a friend of mine, she received a little gift. I mean just some stuff, no big deal, and she was most happy when she got a colored piece of paper (the others pieces of papers she received until then were all white)...
Here is my piece of paper of you... (fill it at your will...)
https://hackernoon.com/my-grandma-and-little-bobby-tables-9911ddfb88bf
https://thedailywtf.com/articles/comments/Open-Sesame
Make a promise. Show up. Do the work. Repeat.