Reading — step 1 of 5
Learn
~1 min readS4 Classes and Functional Programming
R has rich functional programming primitives. The purrr package (tidyverse) extends them, but base R has plenty:
Map — multi-arg apply:
Map(`+`, 1:3, 10:12) # list(11, 13, 15)
Map(function(a, b) a * b, 1:3, c(10, 20, 30)) # list(10, 40, 90)
Filter — keep where predicate is TRUE:
Filter(function(x) x > 2, c(1, 2, 3, 4, 5)) # c(3, 4, 5)
Find — first match:
Find(function(x) x > 3, c(1, 2, 5, 4)) # 5
Reduce — fold:
Reduce(`+`, 1:10) # 55
Reduce(`+`, 1:10, accumulate = TRUE) # running sum
Reduce(function(acc, x) c(acc, x * 2), 1:5, init = c())
# c(2, 4, 6, 8, 10)
Function composition — write your own:
compose <- function(f, g) function(x) f(g(x))
incThenDouble <- compose(function(x) x * 2, function(x) x + 1)
incThenDouble(5) # 12 = (5+1)*2
Partial application:
partial <- function(f, ...) {
args <- list(...)
function(...) do.call(f, c(args, list(...)))
}
add5 <- partial(`+`, 5)
add5(10) # 15
Currying the manual way:
curry <- function(f) {
function(x) function(y) f(x, y)
}
adder <- curry(`+`)
add5 <- adder(5)
add5(10) # 15
Negate — invert a predicate:
is_negative <- Negate(function(x) x >= 0)
is_negative(-5) # TRUE
is_negative(5) # FALSE
do.call(f, args) — call f with args from a list:
do.call(`+`, list(3, 4)) # 7
do.call(paste, list("a", "b", sep = "-")) # "a-b"
Why this matters: R's strength is data manipulation. Functional tools let you express transformations as pipelines of small functions.
With purrr (tidyverse): map, map2, pmap, keep, discard, compose, partial — same ideas, more consistent API.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…