5. Functional Programming
Functional programming
is a style of programming that
treats computation as the evaluation of mathematical functions, and
avoids changing-state and mutable data.
R
has a lot of built in functions such as sapply
, lapply
, and tapply
that encourages the functional style of programming. Additionally, there are helper libraries in R
that makes functional programming easier, such as purrr
. Take a look at the purrr documentation for the full application programming interface API
.
Here, we cover the two most famous functions in functional programming:
map
reduce
5.1. Mapping
Mapping is used to transform a value into another one.
5.1.1. map
You may use the map
function from the library purrr
.
[1]:
library(purrr)
doubleIt <- function(x) 2 * x
a <- map(1:6, doubleIt)
print(paste(a, collapse=','))
[1] "2,4,6,8,10,12"
You may use the base lapply
function.
[2]:
a <- lapply(1:6, doubleIt)
print(paste(a, collapse=','))
[1] "2,4,6,8,10,12"
Anonymous functions
may also be supplied to lapply
or map
.
[3]:
a <- map(1:6, function(x) 3 * x)
print(paste(a, collapse=','))
[1] "3,6,9,12,15,18"
5.1.2. map2
The map2
function allows you to map over 2 lists.
[4]:
a <- map2(1:6, 1:6, function(x, y) x * y)
print(paste(a, collapse=','))
[1] "1,4,9,16,25,36"
5.1.3. pmap
The pmap
function allows you to map over p lists.
[5]:
a <- pmap(list(c(2, 4, 6), c(3, 6, 9), c(4, 8, 12)), function(x, y, z) x + y + z)
print(paste(a, collapse=','))
[1] "9,18,27"
5.1.4. imap
The imap
gives you a hook to the index of the element.
[6]:
a <- imap(10:15, function(i, x) paste(i, ':', x))
print(paste(a, collapse=' | '))
[1] "10 : 1 | 11 : 2 | 12 : 3 | 13 : 4 | 14 : 5 | 15 : 6"
5.1.5. modify
The function modify
will modify elements in a matrix or data frame and return the same type.
[7]:
df <- data.frame(x=1:5, y=6:10)
print(df)
x y
1 1 6
2 2 7
3 3 8
4 4 9
5 5 10
Here, we use an anonymous function to transform the elements.
[8]:
df2 = modify(df, function(x) x * x)
print(df2)
x y
1 1 36
2 4 49
3 9 64
4 16 81
5 25 100
Here, we use a short-hand syntax to transform the elements.
[9]:
df2 = modify(df, ~ .x * .x)
print(df2)
x y
1 1 36
2 4 49
3 9 64
4 16 81
5 25 100
5.2. Reducing
Reducing
collapses an array of elements into a scalar value.
5.2.1. reduce
[10]:
a <- reduce(1:5, function(a, b) a + b)
print(a)
[1] 15
You may also supply an initial value to reduce
.
[11]:
a <- reduce(1:5, function(a, b) a + b, .init=10)
print(a)
[1] 25
5.2.2. accumulate
Accmulate
is like reduce but returns the intermediate results as well.
[12]:
a <- accumulate(1:5, function(a, b) a + b)
print(a)
[1] 1 3 6 10 15
5.3. Filtering
Filter is removing elements from an array.
5.3.1. keep
The keep
function retains elements that satisfies the predicate
.
[13]:
a <- keep(1:10, ~ .x %% 2 == 0)
print(a)
[1] 2 4 6 8 10
5.3.2. discard
The discard
function remove elements that satisifies the predicate
.
[14]:
a <- discard(1:10, ~ .x %%2 != 0)
print(a)
[1] 2 4 6 8 10
5.4. Map, filter, reduce
Let’s put it all together in this simple example. We have a list of numbers that we will
multiply the elements by 3
filter the elements for even numbers
reduce the elements by adding
[15]:
a <- 1:10
b <- map(a, ~ .x * 3)
c <- keep(b, ~ .x %% 2 == 0)
d <- reduce(c, `+`, .init=0)
print(paste(c('[a]', a), collapse=','))
print(paste(c('[b]', b), collapse=','))
print(paste(c('[c]', c), collapse=','))
print(paste(c('d: ', d), collapse=''))
[1] "[a],1,2,3,4,5,6,7,8,9,10"
[1] "[b],3,6,9,12,15,18,21,24,27,30"
[1] "[c],6,12,18,24,30"
[1] "d: 90"