Organising and maintaining functions

9.0.6 Function libraries

#source("stuff.R") #cautious with path
# cautious in which env source is called
# by default source is called in global env
# source in rmd: https://bookdown.org/yihui/rmarkdown-cookbook/source-script.html 

9.0.7 Writing R packages

We can organize code in a source package:

See: https://github.com/gagolews/rpackagedemo for basic/mandatory structure

Also: https://r-pkgs.org/

Ofc: https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Creating-R-packages

9.0.7.1 Building and installing a package

First:

git clone https://github.com/gagolews/rpackagedemo

Second:

#install.packages("stringx")
#install.packages("rpackagedemo/", repos=NULL, type="source")
#library("rpackagedemo")

9.0.8 Documenting

Even if the documetation are in man/ (.Rd files), for once the author recommend
roxygen2. Write specific comment with the function then use roxygen2 to generate the .Rd files.

9.0.9 Writing standalone programs

  • commandArgs(trailingOnly=TRUE)
  • q(save="no", status=1) #status is an integer > 0 = error

I noticed the use of --vanilla and -S from env

Rscript --help
#Combine --no-save, --no-restore, --no-site-file,
#                      --no-init-file and --no-environ

‘sink’ diverts R output to a connection (and must be used again to finish such a diversion, see below!).

sink can be dangerous. In a non-interactive mode you can also use your shell stdout/stderr

9.0.10 Assuring quality code

  • Use git!

  • Read other people code!

Example: https://github.com/r-spatial

9.0.11 Test-driven development

Test-driven development

  • Write test FIRST: it helps explicit assumptions

9.0.11.1 Exercise 9.15

# v1
rms <- function(x) sqrt(mean(x^2))

stopifnot(all.equal(rms(1), 1))
stopifnot(all.equal(rms(1:100), 58.16786054171151931769))
stopifnot(all.equal(rms(rep(pi, 10)), pi))
stopifnot(all.equal(rms(numeric(0)), 0))

# v2
rms <- function(x) { 
    if (length(x) == 0) x <- 0
    sqrt(mean(x^2, na.rm = TRUE))
    }

9.0.11.2 Exercice 9.16

my_sample <- function(x){ 
    if (length(x) == 0 ) return(0)
    if (length(x) == 1 && x == 0) return(0)
    round(runif(x, min(x), max(x)))
}

stopifnot(all.equal(my_sample(1), 1))
stopifnot(all.equal(my_sample(numeric(0)), 0))
stopifnot(all.equal(my_sample(0), 0))

9.0.11.3 Do Stuff with R CMD check

9.0.11.4 Debugging / Profiling

This is nice but seems a bit outside of the scope of the book:

For Debugging -> use print

For profiling -> just keep it in mind that i/o is probably a bottleneck