| Type: | Package | 
| Title: | Functional Programming with Parallelism and Progress Tracking | 
| Version: | 0.5.0 | 
| Maintainer: | Imad EL BADISY <elbadisyimad@gmail.com> | 
| Description: | Provides functional tools such as fmap(), fwalk(), and fapply() to iterate over vectors, data frames, or grouped data with optional parallelism and real-time progress tracking. Designed for readable and reproducible workflows, including support for Monte Carlo simulations and benchmarking. | 
| License: | MIT + file LICENSE | 
| Encoding: | UTF-8 | 
| Imports: | parallel | 
| Suggests: | testthat (≥ 3.0.0), bench, rsample | 
| Config/testthat/edition: | 3 | 
| RoxygenNote: | 7.3.2 | 
| BugReports: | https://github.com/ielbadisy/functionals/issues | 
| NeedsCompilation: | no | 
| Packaged: | 2025-07-15 12:26:32 UTC; imad-el-badisy | 
| Author: | Imad EL BADISY [aut, cre] | 
| Repository: | CRAN | 
| Date/Publication: | 2025-07-18 15:00:08 UTC | 
functionals: Functional programming with parallelism and progress track in R
Description
This package provides a consistent and intuitive API for applying functions over lists, vectors, and data frames, with built-in support for parallelism and progress bars.
Author(s)
Maintainer: Imad EL BADISY elbadisyimad@gmail.com
See Also
Useful links:
- Report bugs at https://github.com/ielbadisy/functionals/issues 
Apply a function over a list or vector with optional parallelism and progress
Description
A lightweight and fast version of 'lapply()' with support for multicore (Unix) and snow-style clusters via 'parallel', with internal progress bar tracking and message suppression.
Usage
fapply(.x, .f, ncores = 1, pb = FALSE, cl = NULL, load_balancing = TRUE, ...)
Arguments
| .x | A list or atomic vector. | 
| .f | Function to apply. | 
| ncores | Number of cores to use (default: 1 = sequential). | 
| pb | Show progress bar? (default: FALSE). | 
| cl | A cluster object (from parallel::makeCluster), or integer for core count. | 
| load_balancing | Logical. Use 'parLapplyLB' if 'TRUE' (default: 'FALSE'). | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results.
Examples
# Basic usage (sequential)
fapply(1:5, sqrt)
# With progress bar (sequential)
fapply(1:5, function(x) { Sys.sleep(0.1); x^2 }, pb = TRUE)
# Multicore on Unix (if available)
if (.Platform$OS.type != "windows") {
  fapply(1:10, sqrt, ncores = 2)
}
# With user-created cluster (portable across platforms)
cl <- parallel::makeCluster(2)
fapply(1:10, sqrt, cl = cl)
parallel::stopCluster(cl)
# Heavy computation example with chunked parallelism
heavy_fn <- function(x) { Sys.sleep(0.05); x^2 }
fapply(1:20, heavy_fn, ncores = 2, pb = TRUE)
Compose multiple functions
Description
Create a new function by composing several functions, applied from right to left. Equivalent to 'f1(f2(f3(...)))'.
Usage
fcompose(...)
Arguments
| ... | Functions to compose. Each must take a single argument and return an object compatible with the next function in the chain. | 
Value
A new function equivalent to nested application of the input functions.
Examples
square <- function(x) x^2
add1 <- function(x) x + 1
f <- fcompose(sqrt, square, add1)  # => sqrt(square(x + 1))
f(4)  # => sqrt((4 + 1)^2) = sqrt(25) = 5
# More compact
fcompose(log, exp)(2)  # log(exp(2)) = 2
Functional Cross-Validation mapping
Description
Applies a user-defined function '.f' to each element of '.splits', typically from cross-validation objects such as 'rsample::vfold_cv()'.
Usage
fcv(.splits, .f, ncores = NULL, pb = FALSE, ...)
Arguments
| .splits | A list of resample splits (e.g., from 'rsample::vfold_cv()'). | 
| .f | A function to apply to each split. Typically expects a single 'split' object. | 
| ncores | Integer. Number of cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to display a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results returned by applying '.f' to each element of '.splits'.
Examples
if (requireNamespace("rsample", quietly = TRUE)) {
  set.seed(123)
  cv_splits <- rsample::vfold_cv(mtcars, v = 5)
  # Apply summary over training sets
  fcv(cv_splits$splits, function(split) {
    summary(rsample::analysis(split))
  })
  # With progress and parallel execution
  
    fcv(cv_splits$splits, function(split) {
      summary(rsample::analysis(split))
    }, ncores = 2, pb = TRUE)
  
}
Functional loop with optional parallelism and progress bar
Description
'floop()' applies a function '.f' to each element of '.x', optionally in parallel, and with an optional progress bar. Unlike 'fwalk()', it can return results or be used purely for side effects (like a for-loop).
Usage
floop(.x, .f, ncores = 1, pb = FALSE, .capture = TRUE, ...)
Arguments
| .x | A vector or list of elements to iterate over. | 
| .f | A function to apply to each element of '.x'. | 
| ncores | Integer. Number of cores to use. Default is 1 (sequential). | 
| pb | Logical. Show a progress bar? Default is 'FALSE'. | 
| .capture | Logical. Should results of '.f' be captured and returned? If 'FALSE', acts like a side-effect loop. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results if '.capture = TRUE', otherwise returns '.x' invisibly.
Examples
# Functional loop that collects output
floop(1:3, function(i) i^2)
# Side-effect only loop (like for-loop with cat)
floop(1:5, function(i) cat(" Processing", i, "\n"), pb = TRUE, .capture = FALSE)
Functional mapping with optional parallelism and progress bars
Description
Applies a function '.f' to each element of '.x', with optional parallel processing and progress bar support.
Usage
fmap(.x, .f, ncores = NULL, pb = FALSE, ...)
Arguments
| .x | A list or atomic vector of elements to iterate over. | 
| .f | A function to apply to each element of '.x'. Can be a function or a string naming a function. | 
| ncores | Integer. Number of CPU cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to show a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results, one for each element of '.x'.
Examples
slow_fn <- function(x) { Sys.sleep(0.01); x^2 }
x <- 1:100
# Basic usage
fmap(x, slow_fn)
# With progress bar
fmap(x, slow_fn, pb = TRUE)
# With parallel execution (non-Windows)
if (.Platform$OS.type != "windows") {
  fmap(x, slow_fn, ncores = 2, pb = TRUE)
}
Apply a function column-wise with name access and parallelism
Description
Applies a function '.f' to each column of a data frame '.df'. Each call receives both the column vector and its name, enabling name-aware column processing. Supports parallel execution and progress display.
Usage
fmapc(.df, .f, ncores = NULL, pb = FALSE, ...)
Arguments
| .df | A data frame whose columns will be iterated over. | 
| .f | A function that takes two arguments: the column vector and its name. | 
| ncores | Integer. Number of cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to display a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results obtained by applying '.f' to each column of '.df'.
Examples
df <- data.frame(a = 1:3, b = 4:6)
# Apply a function that returns column mean and name
fmapc(df, function(x, name) list(mean = mean(x), var = var(x), name = name))
# With progress and parallel execution
fmapc(df, function(x, name) mean(x), ncores = 2, pb = TRUE)
Apply a function to groups of a data frame in parallel
Description
Applies a function '.f' to each group of rows in a data frame '.df', where grouping is defined by one or more variables in 'by'. Each group is passed as a data frame to '.f'. Supports parallelism and optional progress display.
Usage
fmapg(.df, .f, by, ncores = NULL, pb = FALSE, ...)
Arguments
| .df | A data frame to group and apply the function over. | 
| .f | A function to apply to each group. The function should accept a data frame (a group). | 
| by | A character vector of column names in '.df' used for grouping. | 
| ncores | Integer. Number of cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to show a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results, one for each group defined by 'by'.
Examples
# Group-wise mean of Sepal.Length in iris dataset
fmapg(iris, function(df) mean(df$Sepal.Length), by = "Species")
# Group-wise model fitting with progress and parallelism
fmapg(mtcars, function(df) lm(mpg ~ wt, data = df), by = "cyl", ncores = 2, pb = TRUE)
Apply a function over multiple argument lists in parallel
Description
Applies a function '.f' over multiple aligned lists in '.l'. Each element of '.l' should be a list or vector of the same length. Each call to '.f' receives one element from each list. Supports parallel execution and progress display.
Usage
fmapn(.l, .f, ncores = NULL, pb = FALSE, ...)
Arguments
| .l | A list of vectors or lists. All elements must be of equal length. | 
| .f | A function to apply. It must accept as many arguments as there are elements in '.l'. | 
| ncores | Integer. Number of cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to display a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results obtained by applying '.f' to each tuple from '.l'.
Examples
# Fit a linear model for each response variable using the same predictor
df <- data.frame(
  y1 = rnorm(100),
  y2 = rnorm(100),
  x = rnorm(100)
)
# List of formulas and data
formulas <- list(y1 ~ x, y2 ~ x)
data_list <- list(df, df)
fmapn(list(formula = formulas, data = data_list), function(formula, data) {
  lm(formula, data = data)
})
# Extract model summaries in parallel
models <- fmapn(list(formula = formulas, data = data_list), function(formula, data) {
  summary(lm(formula, data = data))$r.squared
})
Apply a function row-wise on a data frame with parallelism
Description
Applies a function '.f' to each row of a data frame '.df', with optional parallelism and progress bar. Each row is converted to a named list before being passed to '.f', enabling flexible access to variables by name.
Usage
fmapr(.df, .f, ncores = NULL, pb = FALSE, ...)
Arguments
| .df | A data frame whose rows will be iterated over. | 
| .f | A function applied to each row, which receives a named list. | 
| ncores | Integer. Number of cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to display a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
A list of results returned by applying '.f' to each row as a list.
Examples
df <- data.frame(name = c("Mister", "Hipster"), age = c(30, 25))
# Create personalized messages
fmapr(df, function(row) paste(row$name, "is", row$age, "years old"))
# Row-wise model formulas
formulas <- data.frame(
  response = c("y1", "y2"),
  predictor = c("x1", "x2"),
  stringsAsFactors = FALSE
)
fmapr(formulas, function(row) {
  reformulate(row$predictor, row$response)
})
Functional reduce
Description
Apply a binary function iteratively over a list or vector, reducing it to a single value or a sequence of intermediate results. This is a wrapper around [Reduce()] that supports optional initial values, right-to-left evaluation, accumulation of intermediate steps, and output simplification.
Usage
freduce(
  .x,
  .f,
  .init = NULL,
  .right = FALSE,
  .accumulate = FALSE,
  .simplify = TRUE
)
Arguments
| .x | A vector or list to reduce. | 
| .f | A binary function to apply. Can be given as a function or quoted (e.g., '\'+\“). | 
| .init | Optional initial value passed to [Reduce()]. If 'NULL', reduction starts from the first two elements. | 
| .right | Logical. If 'TRUE', reduction is performed from right to left. | 
| .accumulate | Logical. If 'TRUE', returns a list of intermediate results (like a scan). | 
| .simplify | Logical. If 'TRUE' and all intermediate results are length 1, the output is simplified to a vector. | 
Value
A single value (default) or a list/vector of intermediate results if '.accumulate = TRUE'.
Examples
freduce(1:5, `+`)                          # => 15
freduce(letters[1:4], paste0)             # => "abcd"
freduce(list(1, 2, 3), `*`)               # => 6
freduce(1:3, `+`, .init = 10)             # => 16
freduce(1:3, paste0, .right = TRUE)       # => "321"
freduce(1:4, `+`, .accumulate = TRUE)     # => c(1, 3, 6, 10)
Repeat an expression or function call multiple times
Description
Repeats an expression or function evaluation 'times' times. If 'expr' is a function, it is invoked with optional input '.x' and additional arguments. If 'expr' is a quoted expression, it is evaluated in the parent environment. Supports parallel processing and optional simplification of results.
Usage
frepeat(
  .x = NULL,
  times,
  expr,
  simplify = FALSE,
  ncores = NULL,
  pb = FALSE,
  ...
)
Arguments
| .x | Optional input passed to 'expr' if 'expr' is a function. Default is 'NULL'. | 
| times | Integer. Number of repetitions. | 
| expr | A function or an unevaluated expression to repeat. If a function, it will be called 'times' times. | 
| simplify | Logical. If 'TRUE', attempts to simplify the result using 'simplify2array()'. Default is 'FALSE'. | 
| ncores | Integer. Number of cores to use for parallel execution. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to display a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to the function 'expr' if it is callable. | 
Value
A list of outputs (or a simplified array if 'simplify = TRUE') from evaluating 'expr' multiple times.
Note
If 'expr' is passed as a function call (not a function or quoted expression),
it will be evaluated immediately, not repeated. Use function(...) \{ ... \} or quote(...) instead.
Examples
# Repeat a pure function call
frepeat(times = 3, expr = function() rnorm(1))
# Repeat a function with input `.x`
frepeat(.x = 10, times = 3, expr = function(x) rnorm(1, mean = x))
# Repeat an unevaluated expression (evaluated with `eval()`)
frepeat(times = 2, expr = quote(rnorm(1)))
# Simplify the output to an array
frepeat(times = 3, expr = function() rnorm(1), simplify = TRUE)
# Monte Carlo simulation: estimate coverage of a 95% CI for sample mean
mc_result <- frepeat(times = 1000, simplify = TRUE, pb = TRUE, ncores = 1, expr = function() {
  sample <- rnorm(30, mean = 0, sd = 1)
  ci <- t.test(sample)$conf.int
  mean(ci[1] <= 0 & 0 <= ci[2])  # check if true mean is inside the interval
})
mean(mc_result)  # estimated coverage
Walk over a vector or list with side effects
Description
Applies a function '.f' to each element of '.x', typically for its side effects (e.g., printing, writing files). This function is the side-effect-friendly equivalent of 'fmap()'. Supports parallel execution and progress bar display.
Usage
fwalk(.x, .f, ncores = NULL, pb = FALSE, ...)
Arguments
| .x | A list or atomic vector of elements to iterate over. | 
| .f | A function to apply to each element of '.x'. Should be called primarily for side effects. | 
| ncores | Integer. Number of cores to use for parallel processing. Default is 'NULL' (sequential). | 
| pb | Logical. Whether to show a progress bar. Default is 'FALSE'. | 
| ... | Additional arguments passed to '.f'. | 
Value
Invisibly returns '.x', like 'purrr::walk()'.
Examples
# Print each element
fwalk(1:3, print)
# Simulate writing files in parallel
fwalk(1:3, function(i) {
  cat(paste("Processing item", i, "\n"))
  Sys.sleep(0.5)
}, ncores = 2, pb = TRUE)