Writing modular code with box

Author

Martin Frigaard

Published

April 5, 2023

ALERT!

This post is currently under development. Thank you for your patience.

What is box?

box is a package…

How box works

To understand how box works, let’s refresh how we normally interact with packages and their functions when using R and developing packages:

  1. Assume I want to use the foo() function from the pkg package. The first step is to install it with install.packages("pkg")

  2. To use the functions in pkg:

    • I need to run library(pkg) in my R session, which loads the pkg namespace ‘and attach[es] it on the search list.

    • If I try to use a function (foo()) from a package (pkg) that hasn’t been loaded with library(pkg) or require(pkg), I see the following:

      foo(x)
      Error in foo(x) : could not find function 'foo'
    • This error can be confusing, because it’s not telling me if the package hasn’t been installed or if the package hasn’t been loaded.

    • If I try to use a function (foo()) from a package (pkg) that hasn’t been installed with install.packages(), I get the following error:

      pkg::foo(x)
      Error in loadNamespace(x) : there is no package called ‘pkg’
      • After installing pkg, I can get around using library(pkg) by being explicit and using pkg::foo(), which tells R I want to use the foo() function from the pkg namespace
    • Read more about namespaces in Advanced R and R packages.

  3. If I am developing an R package, I can include pkg functions in my package by using roxygen2 tags (i.e., #' @importFrom pkg foo)

    • When I use devtools::document(), the tags are converted into directives in the NAMESPACE (i.e., importFrom(pkg,foo))

    • I also need to use usethis::use_package("pkg") to include pkg in the DESCRIPTION under Imports:

The table below shows the connection between roxygen2 tags, the resulting NAMESPACE entry, and what should be listed in the DESCRIPTION (this is also covered in myPkgApp)


Refresher on roxygen2, NAMESPACE & DESCRPTION
roxygen2 tag NAMESPACE directive DESCRIPTION
@importFrom importFrom() : import selected object from another NAMESPACE Imports:
@import import(): import all objects from another package’s NAMESPACE. Imports:
@export export() : export the function, method, generic, or class so it’s available outside of the package (in the NAMESPACE) Nothing


Using box