--- title: "Namespaces - why" author: "Martin Maechler" date: "September 2015 -- April 2016" output: ioslides_presentation --- ## Why do we need **namespaces** in R ? Example from Luke Tierney (2003)'s introductory article on namespaces ```{r} mydnorm <- function(z) 1/sqrt(2 * pi) * exp(- z^2 / 2) mydnorm(-2:2) x <- seq(-5,5, length=100) all.equal(dnorm(x), mydnorm(x)) ``` ## So our function `mydnorm()` is ok, the same as the R builtin `dnorm()` But it is _less_ safe : ```{r} pi <- 3 mydnorm(-2:2) ``` and these are all wrong... because R finds the wrong `pi` in `search()` : ```{r, pi-search} find("pi") search() ``` ## R's `search()` path R finds your object in `search()` - and uses the first found ```{r} search() conflicts() find("pi") ``` What if you use many packages? You get even more conflicts ## Packages in `search()` - conflicts ```{r, Hmisc} require("Hmisc") ``` ```{r} getAnywhere("units") ``` ## More packages ... more conflicts ```{r, dplyr} require("dplyr") ``` ```{r, dplyr-detach, echo=FALSE} detach("package:dplyr") ``` ## require("dplyr") .. [continued] ```{r, dplyr-2, echo=FALSE} sfsmisc :: capture.and.write(suppressWarnings(require("dplyr")), first = 1, last = 15) ``` ## Conflicts in search() -- unavoidable ```{r,pkg-conflicts} conflicts() head(search()) ``` The *solution*: --> *Namespace*s : ... ## Solution: Namespaces *Namespace*s : 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 ```{r, session-show, eval=FALSE} sessionInfo() ## note the " loaded via namespace (and not attached) " ``` ```{r, session-do, echo=FALSE} # simple, but does not fit on one slide: print( sI <- sessionInfo() , locale=FALSE) ``` ## loaded ... (and not attached) `sessionInfo()` ```{r, only-namespace, echo=FALSE} sfsmisc :: capture.and.write(sI, first = 1, last = 12) ```