September 2015

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
## 
## 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

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.3.1 (2016-06-21)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Fedora 24 (Twenty Four)
## 
## attached base packages:
## [1] graphics  grDevices datasets  stats     utils     methods   base     
## 
## other attached packages:
## [1] dplyr_0.5.0     Hmisc_3.17-2    ggplot2_2.1.0   Formula_1.2-1  
## [5] survival_2.39-5 lattice_0.20-34 sfsmisc_1.1-1  
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.7         cluster_2.0.3       knitr_1.14         
##  [4] magrittr_1.5        splines_3.3.1       munsell_0.4.3      
##  [7] colorspace_1.2-7    R6_2.2.0            stringr_1.1.0      
## [10] plyr_1.8.4          tools_3.3.1         nnet_7.3-12        
## [13] grid_3.3.1          gtable_0.2.0        DBI_0.5-1          
## [16] latticeExtra_0.6-28 htmltools_0.3.5     assertthat_0.1     
## [19] yaml_2.1.13         digest_0.6.10       tibble_1.2         
## [22] Matrix_1.2-8        gridExtra_2.2.1     RColorBrewer_1.1-2 
## [25] formatR_1.4         acepack_1.3-3.3     rpart_4.1-10       
## [28] evaluate_0.10       rmarkdown_1.0       stringi_1.1.2      
## [31] scales_0.4.0        foreign_0.8-67

loaded … (and not attached)

sessionInfo()

## R version 3.3.1 (2016-06-21)
##  ....... 
##  ....... 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.7         cluster_2.0.3       knitr_1.14         
##  [4] magrittr_1.5        splines_3.3.1       munsell_0.4.3      
##  [7] colorspace_1.2-7    R6_2.2.0            stringr_1.1.0      
## [10] plyr_1.8.4          tools_3.3.1         nnet_7.3-12        
## [13] grid_3.3.1          gtable_0.2.0        DBI_0.5-1          
## [16] latticeExtra_0.6-28 htmltools_0.3.5     assertthat_0.1     
## [19] yaml_2.1.13         digest_0.6.10       tibble_1.2         
## [22] Matrix_1.2-8        gridExtra_2.2.1     RColorBrewer_1.1-2 
## [25] formatR_1.4         acepack_1.3-3.3     rpart_4.1-10       
## [28] evaluate_0.10       rmarkdown_1.0       stringi_1.1.2      
## [31] scales_0.4.0        foreign_0.8-67