Skip to content

Commit

Permalink
Merge pull request #145 from michaelquinn32/master
Browse files Browse the repository at this point in the history
Implemented accumulate for recursive folding
  • Loading branch information
hadley committed Dec 7, 2015
2 parents 5ff4314 + bbd045a commit 6d4efbe
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 5 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Expand Up @@ -23,4 +23,4 @@ LinkingTo: Rcpp,
BH
URL: https://github.com/hadley/purrr
BugReports: https://github.com/hadley/purrr/issues
RoxygenNote: 5.0.0
RoxygenNote: 5.0.1
2 changes: 2 additions & 0 deletions NAMESPACE
Expand Up @@ -3,6 +3,8 @@
export("%>%")
export("%@%")
export("%||%")
export(accumulate)
export(accumulate_right)
export(array_branch)
export(array_tree)
export(as_function)
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Expand Up @@ -52,3 +52,7 @@

* `zip2()`, `zip3()`, and `zip_n()` have been replaced by `transpose()`.
It does the same thing but the name is better (#128).

* `accumulate()` has been added to handle recursive folding. It is shortand
for `Reduce(f, .x, accumulate = TRUE)` and follows a similar syntax to
`reduce()` (#145). A right-hand version `accumulate_right()` was also added.
54 changes: 50 additions & 4 deletions R/reduce.R
Expand Up @@ -29,20 +29,66 @@
#' list() %>% reduce(`+`)
#' list() %>% reduce(`+`, .init = 0)
reduce <- function(.x, .f, ..., .init) {
force(.f)
f <- function(x, y) .f(x, y, ...)

f <- as_function(.f)
Reduce(f, .x, init = .init)
}

#' @export
#' @rdname reduce
reduce_right <- function(.x, .f, ..., .init) {
force(.f)
.f <- as_function(.f)

# Note the order of arguments is switched
f <- function(x, y) {
.f(y, x, ...)
}

Reduce(f, .x, init = .init, right = TRUE)
}

#' Accumulate recursive folds across a list
#'
#' \code{accumulate} applies a function recursively over a list from the left, while
#' \code{accumulate_right} applies the function from the right. Unlike \code{reduce}
#' both functions keep the intermediate results.
#'
#' @inheritParams reduce
#' @export
#'
#' @examples
#' 1:3 %>% accumulate(`+`)
#' 1:10 %>% accumulate_right(`*`)
#'
#' # From Haskell's scanl documentation
#' 1:10 %>% accumulate(max, .init = 5)
#'
#' # Simulating stochastic processes with drift
#' \dontrun{
#' library(dplyr)
#' library(ggplot2)
#'
#' rerun(5, rnorm(100)) %>%
#' set_names(paste0("sim", 1:5)) %>%
#' map(~ accumulate(., ~ .05 + .x + .y)) %>%
#' map_df(~ data_frame(value = .x, step = 1:100), .id = "simulation") %>%
#' ggplot(aes(x = step, y = value)) +
#' geom_line(aes(color = simulation)) +
#' ggtitle("Simulations of a random walk with drift")
#' }
accumulate <- function(.x, .f, ..., .init) {
f <- as_function(.f)
Reduce(f, .x, init = .init, accumulate = TRUE)
}

#' @export
#' @rdname accumulate
accumulate_right <- function(.x, .f, ..., .init) {
.f <- as_function(.f)

# Note the order of arguments is switched
f <- function(x, y) {
.f(y, x, ...)
}

Reduce(f, .x, init = .init, right = TRUE, accumulate = TRUE)
}
50 changes: 50 additions & 0 deletions man/accumulate.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 6d4efbe

Please sign in to comment.