2 minute read

Exercises����������������������������������������������������������������������������������������������������������������������

Chapter 9 ■ advanCed r programming

You can, for instance, write a generic power function and specialize it for squaring or cubing numbers:

Advertisement

power <- function(n) function(x) x^n square <- power(2) cube <- power(3) x <- 1:4 square(x) ## [1] 1 4 9 16 cube(x) ## [1] 1 8 27 64

This works because the functions returned by power(2) and power(3) live in a context—the closure— where n is known to be 2 and 3, respectively. We have fixed that part of the function we return.

Filter, Map, and Reduce

Three patterns are used again and again in functional programming: filtering, mapping, and reducing. In R, all three are implemented in different functions, but you can write all your programs using the Filter, Map, and Reduce functions.

The Filter function takes a predicate and a vector or list and returns all the elements that satisfy the predicate.

is_even <- function(x) x %% 2 == 0 Filter(is_even, 1:8) ## [1] 2 4 6 8 Filter(is_even, as.list(1:8)) ## [[1]] ## [1] 2 ## ## [[2]] ## [1] 4 ## ## [[3]] ## [1] 6 ## ## [[4]] ## [1] 8

The Map function works like lapply: it applies a function to every element of a vector or list and returns a list of the result. Use unlist to convert it into a vector if that is what you want.

square <- function(x) x^2 Map(square, 1:4) ## [[1]] ## [1] 1 ## ## [[2]] ## [1] 4 ## ## [[3]] ## [1] 9

248

Chapter 9 ■ advanCed r programming

## ## [[4]] ## [1] 16 unlist(Map(square, 1:4)) ## [1] 1 4 9 16

You can do slightly more with Map, though, since Map can be applied to more than one sequence. If you give Map more arguments then these are applied to the function calls as well.

plus <- function(x, y) x + y unlist(Map(plus, 0:3, 3:0)) ## [1] 3 3 3 3

These constructions should be very familiar to you by now so we will leave it at that.

The Reduce function might look less familiar. You can describe what it does in terms of adding or multiplying numbers, and it is in a way a generalization of this. When you write an expression like this:

a + b + c

or

a * b * c

You can think of this as a series of function calls:

`+`(`+`(a, b), c)

or

`*`(`*`(a, b), c)

The Reduce function generalizes this.

Reduce(f, c(a, b, c))

It’s evaluated as follows:

f(f(a, b), c)

You can see this by constructing a function that captures how it is called:

add_parenthesis <- function(a, b) paste("(", a, ", ", b, ")", sep = "") Reduce(add_parenthesis, 1:4) ## [1] "(((1, 2), 3), 4)"

Using Reduce, you could thus easily write your own sum function:

mysum <- function(x) Reduce(`+`, x) sum(1:4) ## [1] 10 mysum(1:4) ## [1] 10

249

This article is from: