September 2015 – April 2016

Why do we need namespaces in R ?

Example from Luke Tierney (2003)'s introductory article on namespaces

mydnorm <- function(z)
 1/sqrt(2 * pi) * exp(- z^2 / 2)

mydnorm(-2:2)
## [1] 0.05399097 0.24197072 0.39894228 0.24197072 0.05399097
x <- seq(-5,5, length=100)
all.equal(dnorm(x), mydnorm(x))
## [1] TRUE

So our function mydnorm() is ok, the same as the R builtin dnorm() But it is less safe :

pi <- 3
mydnorm(-2:2)
## [1] 0.0552504 0.2476151 0.4082483 0.2476151 0.0552504

and these are all wrong… because R finds the wrong pi in search() :

find("pi")
## [1] ".GlobalEnv"   "package:base"
search()
##  [1] ".GlobalEnv"        "package:graphics"  "package:grDevices"
##  [4] "package:datasets"  "package:sfsmisc"   "package:stats"    
##  [7] "package:utils"     "package:methods"   "Autoloads"        
## [10] "package:base"

R's search() path

R finds your object in search() - and uses the first found

search()
##  [1] ".GlobalEnv"        "package:graphics"  "package:grDevices"
##  [4] "package:datasets"  "package:sfsmisc"   "package:stats"    
##  [7] "package:utils"     "package:methods"   "Autoloads"        
## [10] "package:base"
conflicts()
## [1] "body<-"    "kronecker" "pi"
find("pi")
## [1] ".GlobalEnv"   "package:base"

What if you use many packages? You get even more conflicts

Packages in search() - conflicts

require("Hmisc")
## Loading required package: Hmisc
## Loading required package: lattice
## Loading required package: survival
## Loading required package: Formula
## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 3.2.4
## 
## Attaching package: 'Hmisc'
## The following object is masked from 'package:sfsmisc':
## 
##     errbar
## The following objects are masked from 'package:base':
## 
##     format.pval, round.POSIXt, trunc.POSIXt, units
getAnywhere("units")
## 2 differing objects matching 'units' were found
## in the following places
##   package:Hmisc
##   package:base
##   namespace:base
##   namespace:Hmisc
## Use [] to view one of them

More packages … more conflicts

require("dplyr")
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:Hmisc':
## 
##     combine, src, summarize
## The following object is masked from 'package:sfsmisc':
## 
##     last
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

require("dplyr") .. [continued]

## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:Hmisc':
## 
##     combine, src, summarize
## The following object is masked from 'package:sfsmisc':
## 
##     last
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
##  ....... 
##  .......

Conflicts in search() – unavoidable

conflicts()
##  [1] "combine"      "src"          "summarize"    "errbar"      
##  [5] "last"         "filter"       "lag"          "body<-"      
##  [9] "format.pval"  "intersect"    "kronecker"    "pi"          
## [13] "Position"     "round.POSIXt" "setdiff"      "setequal"    
## [17] "trunc.POSIXt" "union"        "units"
head(search())
## [1] ".GlobalEnv"       "package:dplyr"    "package:Hmisc"   
## [4] "package:ggplot2"  "package:Formula"  "package:survival"

The solution: –> Namespaces : …

Solution: Namespaces

Namespaces : complete protection of the functions in a package from "re-definitions" in "globalenv" or other packages:

  • A package must declare where it imports the functions (and objects, e.g., pi) it uses.
  • The package also can use many helper functions and only export the main functions
  • Consequence: Much more modular programming; clean interfaces

Packages & namespaces in R session

sessionInfo() ## note the  " loaded via namespace (and not attached) "
## R version 3.2.3 (2015-12-10)
## Platform: x86_64-redhat-linux-gnu (64-bit)
## Running under: Fedora 22 (Twenty Two)
## 
## attached base packages:
## [1] graphics  grDevices datasets  stats     utils     methods   base     
## 
## other attached packages:
## [1] dplyr_0.4.3     Hmisc_3.17-2    ggplot2_2.1.0   Formula_1.2-1  
## [5] survival_2.38-3 lattice_0.20-33 sfsmisc_1.1-0  
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.4         knitr_1.12          cluster_2.0.3      
##  [4] magrittr_1.5        splines_3.2.3       munsell_0.4.3      
##  [7] colorspace_1.2-6    R6_2.1.2            stringr_1.0.0      
## [10] plyr_1.8.3          tools_3.2.3         parallel_3.2.3     
## [13] nnet_7.3-12         grid_3.2.3          gtable_0.2.0       
## [16] DBI_0.3.1           latticeExtra_0.6-28 htmltools_0.3.5    
## [19] assertthat_0.1      yaml_2.1.13         digest_0.6.9       
## [22] gridExtra_2.2.1     RColorBrewer_1.1-2  formatR_1.3        
## [25] acepack_1.3-3.3     rpart_4.1-10        evaluate_0.8.3     
## [28] rmarkdown_0.9.5     stringi_1.0-1       scales_0.4.0       
## [31] foreign_0.8-66

loaded … (and not attached)

sessionInfo()

## R version 3.2.3 (2015-12-10)
##  ....... 
##  ....... 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.4         knitr_1.12          cluster_2.0.3      
##  [4] magrittr_1.5        splines_3.2.3       munsell_0.4.3      
##  [7] colorspace_1.2-6    R6_2.1.2            stringr_1.0.0      
## [10] plyr_1.8.3          tools_3.2.3         parallel_3.2.3     
## [13] nnet_7.3-12         grid_3.2.3          gtable_0.2.0       
## [16] DBI_0.3.1           latticeExtra_0.6-28 htmltools_0.3.5    
## [19] assertthat_0.1      yaml_2.1.13         digest_0.6.9       
## [22] gridExtra_2.2.1     RColorBrewer_1.1-2  formatR_1.3        
## [25] acepack_1.3-3.3     rpart_4.1-10        evaluate_0.8.3     
## [28] rmarkdown_0.9.5     stringi_1.0-1       scales_0.4.0       
## [31] foreign_0.8-66