# 8 Function factories

## 8.1 Prerequisites

## 8.2 Factory fundamentals

**Q**: Base R contains two function factories,`approxfun()`

and`ecdf()`

. Read their documentation and experiment to figure out what the functions do and what they return.**A**:**Q**: Create a function`pick()`

that takes an index,`i`

, as an argument and returns a function with an argument`x`

that subsets`x`

with`i`

.`pick(1)(x) # should be equivalent to x[[1]] lapply(mtcars, pick(5)) # should be equivalent to lapply(mtcars, function(x) x[[5]])`

**A**:**Q**: Create a function that creates functions that compute the i^{th}central moment of a numeric vector. You can test it by running the following code:`m1 <- moment(1) m2 <- moment(2) x <- runif(100) stopifnot(all.equal(m1(x), 0)) stopifnot(all.equal(m2(x), var(x) * 99 / 100))`

**A**:**Q**: What happens if you don’t use a closure? Make predictions, then verify with the code below.**A**:**Q**: What happens if you use`<-`

instead of`<<-`

? Make predictions, then verify with the code below.**A**:

## 8.3 Graphical factories

**Q**: Compare and contrast`ggplot2::label_bquote()`

with`scales::number_format()`

.**A**:

## 8.4 Statistical factories

**Q**: In`boot_model()`

, why don’t I need to force the evaluation of`df`

or`model`

?**A**:**Q**: Why might you formulate the Box-Cox transformation like this?`boxcox3 <- function(x) { function(lambda) { if (lambda == 0) { log(x) } else { (x ^ lambda - 1) / lambda } } }`

**A**:**Q**: Why don’t you need to worry that`boot_permute()`

stores a copy of the data inside the function that it generates?**A**:**Q**: How much time does`ll_poisson2()`

save compared to`ll_poisson1()`

? Use`bench::mark()`

to see how much faster the optimisation occurs. How does changing the length of`x`

change the results?**A**:

## 8.5 Function factories + functionals

**Q**: Which of the following commands is equivalent to`with(x, f(z))`

?`x$f(x$z)`

.`f(x$z)`

.`x$f(z)`

.`f(z)`

.- It depends.

**A**:**Q**: Compare and contrast the effects of`env_bind()`

vs.`attach()`

for the following code.`funs <- list( mean = function(x) mean(x, na.rm = TRUE), sum = function(x) sum(x, na.rm = TRUE) ) attach(funs) #> The following objects are masked from package:base: #> #> mean, sum mean <- function(x) stop("Hi!") detach(funs) env_bind(globalenv(), !!!funs) mean <- function(x) stop("Hi!") env_unbind(globalenv(), names(funs))`

**A**:

## 8.6 Old exercises

## 8.7 Closures

**Q**: Why are functions created by other functions called closures?

**A**: As stated in the book:because they enclose the environment of the parent function and can access all its variables.

**Q**: What does the following statistical function do? What would be a better name for it? (The existing name is a bit of a hint.)`bc <- function(lambda) { if (lambda == 0) { function(x) log(x) } else { function(x) (x ^ lambda - 1) / lambda } }`

**A**: It is the logarithm, when lambda equals zero and`x ^ lambda - 1 / lambda`

otherwise. A better name might be`box_cox_transformation`

(one parametric), you can read about it (here)[https://en.wikipedia.org/wiki/Power_transform].**Q**: What does`approxfun()`

do? What does it return?

**A**:`approxfun`

basically takes a combination of 2-dimensional data points + some extra specifications as arguments and returns a stepwise linear or constant interpolation function (defined on the range of given x-values, by default).**Q**: What does`ecdf()`

do? What does it return?

**A**: “ecdf” means empirical density function. For a numeric vector,`ecdf()`

returns the appropriate density function (of class “ecdf”, which is inheriting from class “stepfun”). You can describe it’s behaviour in 2 steps. In the first part of it’s body, the`(x,y)`

pairs for the nodes of the density function are calculated. In the second part these pairs are given to`approxfun`

.**Q**: Create a function that creates functions that compute the ith central moment of a numeric vector. You can test it by running the following code:`m1 <- moment(1) m2 <- moment(2) x <- runif(100) stopifnot(all.equal(m1(x), 0)) stopifnot(all.equal(m2(x), var(x) * 99 / 100))`

**A**: For a discrete formulation look here**Q**: Create a function`pick()`

that takes an index,`i`

, as an argument and returns a function with an argument`x`

that subsets`x`

with`i`

.**A**:

## 8.8 Case study: numerical integration

**Q**: Instead of creating individual functions (e.g.,`midpoint()`

,`trapezoid()`

,`simpson()`

, etc.), we could store them in a list. If we did that, how would that change the code? Can you create the list of functions from a list of coefficients for the Newton-Cotes formulae?

**A**:**Q**: The trade-off between integration rules is that more complex rules are slower to compute, but need fewer pieces. For`sin()`

in the range [0, \(\pi\)], determine the number of pieces needed so that each rule will be equally accurate. Illustrate your results with a graph. How do they change for different functions?`sin(1 / x^2)`

is particularly challenging.

**A**: