purrr/ 0000755 0001762 0000144 00000000000 14465116667 011444 5 ustar ligges users purrr/NAMESPACE 0000644 0001762 0000144 00000007523 14460273713 012661 0 ustar ligges users # Generated by roxygen2: do not edit by hand
S3method(as_mapper,character)
S3method(as_mapper,default)
S3method(as_mapper,list)
S3method(as_mapper,numeric)
S3method(print,purrr_function_compose)
S3method(print,purrr_function_partial)
S3method(print,purrr_rate_backoff)
S3method(print,purrr_rate_delay)
S3method(rate_sleep,purrr_rate_backoff)
S3method(rate_sleep,purrr_rate_delay)
export("%>%")
export("%@%")
export("%||%")
export("pluck<-")
export(accumulate)
export(accumulate2)
export(accumulate_right)
export(array_branch)
export(array_tree)
export(as_mapper)
export(as_vector)
export(assign_in)
export(at_depth)
export(attr_getter)
export(auto_browse)
export(chuck)
export(compact)
export(compose)
export(cross)
export(cross2)
export(cross3)
export(cross_d)
export(cross_df)
export(cross_n)
export(detect)
export(detect_index)
export(discard)
export(discard_at)
export(done)
export(every)
export(exec)
export(flatten)
export(flatten_chr)
export(flatten_dbl)
export(flatten_df)
export(flatten_dfc)
export(flatten_dfr)
export(flatten_int)
export(flatten_lgl)
export(flatten_raw)
export(has_element)
export(head_while)
export(imap)
export(imap_chr)
export(imap_dbl)
export(imap_dfc)
export(imap_dfr)
export(imap_int)
export(imap_lgl)
export(imap_raw)
export(imodify)
export(insistently)
export(invoke)
export(invoke_map)
export(invoke_map_chr)
export(invoke_map_dbl)
export(invoke_map_df)
export(invoke_map_dfc)
export(invoke_map_dfr)
export(invoke_map_int)
export(invoke_map_lgl)
export(invoke_map_raw)
export(is_atomic)
export(is_bare_atomic)
export(is_bare_character)
export(is_bare_double)
export(is_bare_integer)
export(is_bare_list)
export(is_bare_logical)
export(is_bare_numeric)
export(is_bare_vector)
export(is_character)
export(is_double)
export(is_empty)
export(is_formula)
export(is_function)
export(is_integer)
export(is_list)
export(is_logical)
export(is_null)
export(is_rate)
export(is_scalar_atomic)
export(is_scalar_character)
export(is_scalar_double)
export(is_scalar_integer)
export(is_scalar_list)
export(is_scalar_logical)
export(is_scalar_vector)
export(is_vector)
export(iwalk)
export(keep)
export(keep_at)
export(lift)
export(lift_dl)
export(lift_dv)
export(lift_ld)
export(lift_lv)
export(lift_vd)
export(lift_vl)
export(list_along)
export(list_assign)
export(list_c)
export(list_cbind)
export(list_flatten)
export(list_merge)
export(list_modify)
export(list_rbind)
export(list_simplify)
export(list_transpose)
export(lmap)
export(lmap_at)
export(lmap_if)
export(map)
export(map2)
export(map2_chr)
export(map2_dbl)
export(map2_df)
export(map2_dfc)
export(map2_dfr)
export(map2_int)
export(map2_lgl)
export(map2_raw)
export(map2_vec)
export(map_at)
export(map_chr)
export(map_dbl)
export(map_depth)
export(map_df)
export(map_dfc)
export(map_dfr)
export(map_if)
export(map_int)
export(map_lgl)
export(map_raw)
export(map_vec)
export(modify)
export(modify2)
export(modify_at)
export(modify_depth)
export(modify_if)
export(modify_in)
export(modify_tree)
export(negate)
export(none)
export(partial)
export(pluck)
export(pluck_depth)
export(pluck_exists)
export(pmap)
export(pmap_chr)
export(pmap_dbl)
export(pmap_df)
export(pmap_dfc)
export(pmap_dfr)
export(pmap_int)
export(pmap_lgl)
export(pmap_raw)
export(pmap_vec)
export(possibly)
export(prepend)
export(pwalk)
export(quietly)
export(rate_backoff)
export(rate_delay)
export(rate_reset)
export(rate_sleep)
export(rbernoulli)
export(rdunif)
export(reduce)
export(reduce2)
export(reduce2_right)
export(reduce_right)
export(rep_along)
export(rerun)
export(safely)
export(set_names)
export(simplify)
export(simplify_all)
export(slowly)
export(some)
export(splice)
export(tail_while)
export(transpose)
export(update_list)
export(vec_depth)
export(walk)
export(walk2)
export(when)
export(zap)
import(rlang)
import(vctrs)
importFrom(cli,cli_progress_bar)
importFrom(lifecycle,deprecated)
importFrom(magrittr,"%>%")
useDynLib(purrr, .registration = TRUE)
purrr/LICENSE 0000644 0001762 0000144 00000000053 14304371054 012430 0 ustar ligges users YEAR: 2020
COPYRIGHT HOLDER: purrr authors
purrr/tools/ 0000755 0001762 0000144 00000000000 14330306457 012571 5 ustar ligges users purrr/tools/examples.R 0000644 0001762 0000144 00000001040 14330306457 014525 0 ustar ligges users if (getRversion() < "4.1") {
dir.create("man/macros", showWarnings = FALSE, recursive = TRUE)
cat(
paste(
"\\renewcommand{\\examples}{\\section{Examples}{",
"These examples are designed to work in R >= 4.1 so that we can take",
"advantage of modern syntax like the base pipe (\\verb{|>}) and the ",
"function shorthand (\\verb{\\(x) x + 1}). They might not work on the ",
"version of R that you're using.",
"\\preformatted{#1}}}",
collapse = ""
),
file = "man/macros/examples.Rd"
)
}
purrr/README.md 0000644 0001762 0000144 00000005015 14355574066 012723 0 ustar ligges users
# purrr
[](https://cran.r-project.org/package=purrr)
[](https://app.codecov.io/gh/tidyverse/purrr?branch=master)
[](https://github.com/tidyverse/purrr/actions)
## Overview
purrr enhances R’s functional programming (FP) toolkit by providing a
complete and consistent set of tools for working with functions and
vectors. If you’ve never heard of FP before, the best place to start is
the family of `map()` functions which allow you to replace many for
loops with code that is both more succinct and easier to read. The best
place to learn about the `map()` functions is the [iteration
chapter](https://r4ds.had.co.nz/iteration.html) in R for data science.
## Installation
``` r
# The easiest way to get purrr is to install the whole tidyverse:
install.packages("tidyverse")
# Alternatively, install just purrr:
install.packages("purrr")
# Or the the development version from GitHub:
# install.packages("remotes")
remotes::install_github("tidyverse/purrr")
```
## Cheatsheet
## Usage
The following example uses purrr to solve a fairly realistic problem:
split a data frame into pieces, fit a model to each piece, compute the
summary, then extract the R2.
``` r
library(purrr)
mtcars |>
split(mtcars$cyl) |> # from base R
map(\(df) lm(mpg ~ wt, data = df)) |>
map(summary) %>%
map_dbl("r.squared")
#> 4 6 8
#> 0.5086326 0.4645102 0.4229655
```
This example illustrates some of the advantages of purrr functions over
the equivalents in base R:
- The first argument is always the data, so purrr works naturally with
the pipe.
- All purrr functions are type-stable. They always return the advertised
output type (`map()` returns lists; `map_dbl()` returns double
vectors), or they throw an error.
- All `map()` functions accept functions (named, anonymous, and lambda),
character vector (used to extract components by name), or numeric
vectors (used to extract by position).
purrr/man/ 0000755 0001762 0000144 00000000000 14464464653 012217 5 ustar ligges users purrr/man/pmap.Rd 0000644 0001762 0000144 00000011154 14460311734 013430 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/pmap.R
\name{pmap}
\alias{pmap}
\alias{pmap_lgl}
\alias{pmap_int}
\alias{pmap_dbl}
\alias{pmap_chr}
\alias{pmap_vec}
\alias{pwalk}
\title{Map over multiple input simultaneously (in "parallel")}
\usage{
pmap(.l, .f, ..., .progress = FALSE)
pmap_lgl(.l, .f, ..., .progress = FALSE)
pmap_int(.l, .f, ..., .progress = FALSE)
pmap_dbl(.l, .f, ..., .progress = FALSE)
pmap_chr(.l, .f, ..., .progress = FALSE)
pmap_vec(.l, .f, ..., .ptype = NULL, .progress = FALSE)
pwalk(.l, .f, ..., .progress = FALSE)
}
\arguments{
\item{.l}{A list of vectors. The length of \code{.l} determines the number of
arguments that \code{.f} will be called with. Arguments will be supply by
position if unnamed, and by name if named.
Vectors of length 1 will be recycled to any length; all other elements
must be have the same length.
A data frame is an important special case of \code{.l}. It will cause \code{.f}
to be called once for each row.}
\item{.f}{A function, specified in one of the following ways:
\itemize{
\item A named function.
\item An anonymous function, e.g. \verb{\\(x, y, z) x + y / z} or
\code{function(x, y, z) x + y / z}
\item A formula, e.g. \code{~ ..1 + ..2 / ..3}. This syntax is not recommended as
you can only refer to arguments by position.
}}
\item{...}{Additional arguments passed on to the mapped function.
We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
\if{html}{\out{
}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{
}}
This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}
\item{.progress}{Whether to show a progress bar. Use \code{TRUE} to turn on
a basic progress bar, use a string to give it a name, or see
\link{progress_bars} for more details.}
\item{.ptype}{If \code{NULL}, the default, the output type is the common type
of the elements of the result. Otherwise, supply a "prototype" giving
the desired type of output.}
}
\value{
The output length is determined by the length of the input.
The output names are determined by the input names.
The output type is determined by the suffix:
\itemize{
\item No suffix: a list; \code{.f()} can return anything.
\item \verb{_lgl()}, \verb{_int()}, \verb{_dbl()}, \verb{_chr()} return a logical, integer, double,
or character vector respectively; \code{.f()} must return a compatible atomic
vector of length 1.
\item \verb{_vec()} return an atomic or S3 vector, the same type that \code{.f} returns.
\code{.f} can return pretty much any type of vector, as long as its length 1.
\item \code{walk()} returns the input \code{.x} (invisibly). This makes it easy to
use in a pipe. The return value of \code{.f()} is ignored.
}
Any errors thrown by \code{.f} will be wrapped in an error with class
\link{purrr_error_indexed}.
}
\description{
These functions are variants of \code{\link[=map]{map()}} that iterate over multiple arguments
simultaneously. They are parallel in the sense that each input is processed
in parallel with the others, not in the sense of multicore computing, i.e.
they share the same notion of "parallel" as \code{\link[base:Extremes]{base::pmax()}} and \code{\link[base:Extremes]{base::pmin()}}.
}
\examples{
x <- list(1, 1, 1)
y <- list(10, 20, 30)
z <- list(100, 200, 300)
pmap(list(x, y, z), sum)
# Matching arguments by position
pmap(list(x, y, z), function(first, second, third) (first + third) * second)
# Matching arguments by name
l <- list(a = x, b = y, c = z)
pmap(l, function(c, b, a) (a + c) * b)
# Vectorizing a function over multiple arguments
df <- data.frame(
x = c("apple", "banana", "cherry"),
pattern = c("p", "n", "h"),
replacement = c("P", "N", "H"),
stringsAsFactors = FALSE
)
pmap(df, gsub)
pmap_chr(df, gsub)
# Use `...` to absorb unused components of input list .l
df <- data.frame(
x = 1:3,
y = 10:12,
z = letters[1:3]
)
plus <- function(x, y) x + y
\dontrun{
# this won't work
pmap(df, plus)
}
# but this will
plus2 <- function(x, y, ...) x + y
pmap_dbl(df, plus2)
# The "p" for "parallel" in pmap() is the same as in base::pmin()
# and base::pmax()
df <- data.frame(
x = c(1, 2, 5),
y = c(5, 4, 8)
)
# all produce the same result
pmin(df$x, df$y)
map2_dbl(df$x, df$y, min)
pmap_dbl(df, min)
}
\seealso{
Other map variants:
\code{\link{imap}()},
\code{\link{lmap}()},
\code{\link{map2}()},
\code{\link{map_depth}()},
\code{\link{map_if}()},
\code{\link{map}()},
\code{\link{modify}()}
}
\concept{map variants}
purrr/man/list_transpose.Rd 0000644 0001762 0000144 00000005713 14313364271 015551 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/list-transpose.R
\name{list_transpose}
\alias{list_transpose}
\title{Transpose a list}
\usage{
list_transpose(
x,
...,
template = NULL,
simplify = NA,
ptype = NULL,
default = NULL
)
}
\arguments{
\item{x}{A list of vectors to transpose.}
\item{...}{These dots are for future extensions and must be empty.}
\item{template}{A "template" that describes the output list. Can either be
a character vector (where elements are extracted by name), or an integer
vector (where elements are extracted by position). Defaults to the names
of the first element of \code{x}, or if they're not present, the integer
indices.}
\item{simplify}{Should the result be \link[=list_simplify]{simplified}?
\itemize{
\item \code{TRUE}: simplify or die trying.
\item \code{NA}: simplify if possible.
\item \code{FALSE}: never try to simplify, always leaving as a list.
}
Alternatively, a named list specifying the simplification by output
element.}
\item{ptype}{An optional vector prototype used to control the simplification.
Alternatively, a named list specifying the prototype by output element.}
\item{default}{A default value to use if a value is absent or \code{NULL}.
Alternatively, a named list specifying the default by output element.}
}
\description{
\code{list_transpose()} turns a list-of-lists "inside-out". For instance it turns a pair of
lists into a list of pairs, or a list of pairs into a pair of lists. For
example, if you had a list of length \code{n} where each component had values \code{a}
and \code{b}, \code{list_transpose()} would make a list with elements \code{a} and
\code{b} that contained lists of length \code{n}.
It's called transpose because \code{x[["a"]][["b"]]} is equivalent to
\code{list_transpose(x)[["b"]][["a"]]}, i.e. transposing a list flips the order of
indices in a similar way to transposing a matrix.
}
\examples{
# list_transpose() is useful in conjunction with safely()
x <- list("a", 1, 2)
y <- x |> map(safely(log))
y |> str()
# Put all the errors and results together
y |> list_transpose() |> str()
# Supply a default result to further simplify
y |> list_transpose(default = list(result = NA)) |> str()
# list_transpose() will try to simplify by default:
x <- list(list(a = 1, b = 2), list(a = 3, b = 4), list(a = 5, b = 6))
x |> list_transpose()
# this makes list_tranpose() not completely symmetric
x |> list_transpose() |> list_transpose()
# use simplify = FALSE to always return lists:
x |> list_transpose(simplify = FALSE) |> str()
x |>
list_transpose(simplify = FALSE) |>
list_transpose(simplify = FALSE) |> str()
# Provide an explicit template if you know which elements you want to extract
ll <- list(
list(x = 1, y = "one"),
list(z = "deux", x = 2)
)
ll |> list_transpose()
ll |> list_transpose(template = c("x", "y", "z"))
ll |> list_transpose(template = 1)
# And specify a default if you want to simplify
ll |> list_transpose(template = c("x", "y", "z"), default = NA)
}
purrr/man/array-coercion.Rd 0000644 0001762 0000144 00000003710 14311356421 015404 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/arrays.R
\name{array-coercion}
\alias{array-coercion}
\alias{array_branch}
\alias{array_tree}
\title{Coerce array to list}
\usage{
array_branch(array, margin = NULL)
array_tree(array, margin = NULL)
}
\arguments{
\item{array}{An array to coerce into a list.}
\item{margin}{A numeric vector indicating the positions of the
indices to be to be enlisted. If \code{NULL}, a full margin is
used. If \code{numeric(0)}, the array as a whole is wrapped in a
list.}
}
\description{
\code{array_branch()} and \code{array_tree()} enable arrays to be
used with purrr's functionals by turning them into lists. The
details of the coercion are controlled by the \code{margin}
argument. \code{array_tree()} creates an hierarchical list (a tree)
that has as many levels as dimensions specified in \code{margin},
while \code{array_branch()} creates a flat list (by analogy, a
branch) along all mentioned dimensions.
}
\details{
When no margin is specified, all dimensions are used by
default. When \code{margin} is a numeric vector of length zero, the
whole array is wrapped in a list.
}
\examples{
# We create an array with 3 dimensions
x <- array(1:12, c(2, 2, 3))
# A full margin for such an array would be the vector 1:3. This is
# the default if you don't specify a margin
# Creating a branch along the full margin is equivalent to
# as.list(array) and produces a list of size length(x):
array_branch(x) |> str()
# A branch along the first dimension yields a list of length 2
# with each element containing a 2x3 array:
array_branch(x, 1) |> str()
# A branch along the first and third dimensions yields a list of
# length 2x3 whose elements contain a vector of length 2:
array_branch(x, c(1, 3)) |> str()
# Creating a tree from the full margin creates a list of lists of
# lists:
array_tree(x) |> str()
# The ordering and the depth of the tree are controlled by the
# margin argument:
array_tree(x, c(3, 1)) |> str()
}
purrr/man/chuck.Rd 0000644 0001762 0000144 00000002471 14310436312 013564 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/pluck.R
\name{chuck}
\alias{chuck}
\title{Get an element deep within a nested data structure, failing if it doesn't
exist}
\usage{
chuck(.x, ...)
}
\arguments{
\item{.x}{A vector or environment}
\item{...}{A list of accessors for indexing into the object. Can be
an positive integer, a negative integer (to index from the right),
a string (to index into names), or an accessor function
(except for the assignment variants which only support names and
positions). If the object being indexed is an S4 object,
accessing it by name will return the corresponding slot.
\link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if
your accessors are stored in a list, you can splice that in with
\verb{!!!}.}
}
\description{
\code{chuck()} implements a generalised form of \code{[[} that allow you to index
deeply and flexibly into data structures. If the index you are trying to
access does not exist (or is \code{NULL}), it will throw (i.e. chuck) an error.
}
\examples{
x <- list(a = 1, b = 2)
# When indexing an element that doesn't exist `[[` sometimes returns NULL:
x[["y"]]
# and sometimes errors:
try(x[[3]])
# chuck() consistently errors:
try(chuck(x, "y"))
try(chuck(x, 3))
}
\seealso{
\code{\link[=pluck]{pluck()}} for a quiet equivalent.
}
purrr/man/modify_in.Rd 0000644 0001762 0000144 00000003417 14311356421 014450 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/pluck-assign.R
\name{modify_in}
\alias{modify_in}
\alias{assign_in}
\title{Modify a pluck location}
\usage{
modify_in(.x, .where, .f, ...)
assign_in(x, where, value)
}
\arguments{
\item{.x, x}{A vector or environment}
\item{.where, where}{A pluck location, as a numeric vector of
positions, a character vector of names, or a list combining both.
The location must exist in the data structure.}
\item{.f}{A function to apply at the pluck location given by \code{.where}.}
\item{...}{Arguments passed to \code{.f}.}
\item{value}{A value to replace in \code{.x} at the pluck location.
Use \code{zap()} to instead remove the element.}
}
\description{
\itemize{
\item \code{assign_in()} takes a data structure and a \link{pluck} location,
assigns a value there, and returns the modified data structure.
\item \code{modify_in()} applies a function to a pluck location, assigns the
result back to that location with \code{\link[=assign_in]{assign_in()}}, and returns the
modified data structure.
}
}
\examples{
# Recall that pluck() returns a component of a data structure that
# might be arbitrarily deep
x <- list(list(bar = 1, foo = 2))
pluck(x, 1, "foo")
# Use assign_in() to modify the pluck location:
str(assign_in(x, list(1, "foo"), 100))
# Or zap to remove it
str(assign_in(x, list(1, "foo"), zap()))
# Like pluck(), this works even when the element (or its parents) don't exist
pluck(x, 1, "baz")
str(assign_in(x, list(2, "baz"), 100))
# modify_in() applies a function to that location and update the
# element in place:
modify_in(x, list(1, "foo"), \(x) x * 200)
# Additional arguments are passed to the function in the ordinary way:
modify_in(x, list(1, "foo"), `+`, 100)
}
\seealso{
\code{\link[=pluck]{pluck()}}
}
purrr/man/rate_sleep.Rd 0000644 0001762 0000144 00000001434 14304371054 014614 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/rate.R
\name{rate_sleep}
\alias{rate_sleep}
\alias{rate_reset}
\title{Wait for a given time}
\usage{
rate_sleep(rate, quiet = TRUE)
rate_reset(rate)
}
\arguments{
\item{rate}{A \link[=rate_backoff]{rate} object determining the waiting time.}
\item{quiet}{If \code{FALSE}, prints a message displaying how long until
the next request.}
}
\description{
If the rate's internal counter exceeds the maximum number of times
it is allowed to sleep, \code{rate_sleep()} throws an error of class
\code{purrr_error_rate_excess}.
}
\details{
Call \code{rate_reset()} to reset the internal rate counter to 0.
}
\seealso{
\code{\link[=rate_backoff]{rate_backoff()}}, \code{\link[=insistently]{insistently()}}
}
\keyword{internal}
purrr/man/purrr_error_indexed.Rd 0000644 0001762 0000144 00000012037 14355607172 016566 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/map.R
\name{purrr_error_indexed}
\alias{purrr_error_indexed}
\title{Indexed errors (\code{purrr_error_indexed})}
\description{
The \code{purrr_error_indexed} class is thrown by \code{\link[=map]{map()}}, \code{\link[=map2]{map2()}}, \code{\link[=pmap]{pmap()}}, and friends.
It wraps errors thrown during the processing on individual elements with information about the location of the error.
}
\section{Structure}{
\code{purrr_error_indexed} has three important fields:
\itemize{
\item \code{location}: the location of the error as a single integer.
\item \code{name}: the name of the location as a string. If the element was not named, \code{name} will be \code{NULL}
\item \code{parent}: the original error thrown by \code{.f}.
}
Let's see this in action by capturing the generated condition from a very simple example:
\if{html}{\out{
}}\preformatted{f <- function(x) \{
rlang::abort("This is an error")
\}
cnd <- rlang::catch_cnd(map(c(1, 4, 2), f))
class(cnd)
#> [1] "purrr_error_indexed" "rlang_error" "error"
#> [4] "condition"
cnd$location
#> [1] 1
cnd$name
#> NULL
print(cnd$parent, backtrace = FALSE)
#>
#> Error in `.f()`:
#> ! This is an error
}\if{html}{\out{
}}
If the input vector is named, \code{name} will be non-\code{NULL}:
\if{html}{\out{
}}\preformatted{cnd <- rlang::catch_cnd(map(c(a = 1, b = 4, c = 2), f))
cnd$name
#> [1] "a"
}\if{html}{\out{
}}
}
\section{Handling errors}{
(This section assumes that you're familiar with the basics of error handling in R, as described in \href{https://adv-r.hadley.nz/conditions.html}{Advanced R}.)
This error chaining is really useful when doing interactive data analysis, but it adds some extra complexity when handling errors with \code{tryCatch()} or \code{withCallingHandlers()}.
Let's see what happens by adding a custom class to the error thrown by \code{f()}:
\if{html}{\out{
}}\preformatted{f <- function(x) \{
rlang::abort("This is an error", class = "my_error")
\}
map(c(1, 4, 2, 5, 3), f)
#> Error in `map()`:
#> i In index: 1.
#> Caused by error in `.f()`:
#> ! This is an error
}\if{html}{\out{
}}
This doesn't change the visual display, but you might be surprised if you try to catch this error with \code{tryCatch()} or \code{withCallingHandlers()}:
\if{html}{\out{
}}\preformatted{tryCatch(
map(c(1, 4, 2, 5, 3), f),
my_error = function(err) \{
# use NULL value if error
NULL
\}
)
#> Error in `map()`:
#> i In index: 1.
#> Caused by error in `.f()`:
#> ! This is an error
withCallingHandlers(
map(c(1, 4, 2, 5, 3), f),
my_error = function(err) \{
# throw a more informative error
abort("Wrapped error", parent = err)
\}
)
#> Error in `map()`:
#> i In index: 1.
#> Caused by error in `.f()`:
#> ! This is an error
}\if{html}{\out{
}}
That's because, as described above, the error that \code{map()} throws will always have class \code{purrr_error_indexed}:
\if{html}{\out{
}}\preformatted{tryCatch(
map(c(1, 4, 2, 5, 3), f),
purrr_error_indexed = function(err) \{
print("Hello! I am now called :)")
\}
)
#> [1] "Hello! I am now called :)"
}\if{html}{\out{
}}
In order to handle the error thrown by \code{f()}, you'll need to use \code{rlang::cnd_inherits()} on the parent error:
\if{html}{\out{
}}\preformatted{tryCatch(
map(c(1, 4, 2, 5, 3), f),
purrr_error_indexed = function(err) \{
if (rlang::cnd_inherits(err, "my_error")) \{
NULL
\} else \{
rlang::cnd_signal(err)
\}
\}
)
#> NULL
withCallingHandlers(
map(c(1, 4, 2, 5, 3), f),
purrr_error_indexed = function(err) \{
if (rlang::cnd_inherits(err, "my_error")) \{
abort("Wrapped error", parent = err)
\}
\}
)
#> Error:
#> ! Wrapped error
#> Caused by error in `map()`:
#> i In index: 1.
#> Caused by error in `.f()`:
#> ! This is an error
}\if{html}{\out{
}}
(The \code{tryCatch()} approach is suboptimal because we're no longer just handling errors, but also rethrowing them.
The rethrown errors won't work correctly with (e.g.) \code{recover()} and \code{traceback()}, but we don't currently have a better approach.
In the future we expect to \href{https://github.com/r-lib/rlang/issues/1534}{enhance \code{try_fetch()}} to make this easier to do 100\% correctly).
Finally, if you just want to get rid of purrr's wrapper error, you can resignal the parent error:
\if{html}{\out{
}}\preformatted{withCallingHandlers(
map(c(1, 4, 2, 5, 3), f),
purrr_error_indexed = function(err) \{
rlang::cnd_signal(err$parent)
\}
)
#> Error in `.f()`:
#> ! This is an error
}\if{html}{\out{
}}
Because we are resignalling an error, it's important to use \code{withCallingHandlers()} and not \code{tryCatch()} in order to preserve the full backtrace context.
That way \code{recover()}, \code{traceback()}, and related tools will continue to work correctly.
}
\keyword{internal}
purrr/man/reduce_right.Rd 0000644 0001762 0000144 00000004332 14314671330 015136 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/reduce.R
\name{reduce_right}
\alias{reduce_right}
\alias{reduce2_right}
\alias{accumulate_right}
\title{Reduce from the right (retired)}
\usage{
reduce_right(.x, .f, ..., .init)
reduce2_right(.x, .y, .f, ..., .init)
accumulate_right(.x, .f, ..., .init)
}
\arguments{
\item{.x}{A list or atomic vector.}
\item{.f}{For \code{reduce()}, a 2-argument function. The function will be passed
the accumulated value as the first argument and the "next" value as the
second argument.
For \code{reduce2()}, a 3-argument function. The function will be passed the
accumulated value as the first argument, the next value of \code{.x} as the
second argument, and the next value of \code{.y} as the third argument.
The reduction terminates early if \code{.f} returns a value wrapped in
a \code{\link[=done]{done()}}.}
\item{...}{Additional arguments passed on to the mapped function.
We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
\if{html}{\out{
}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{
}}
This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}
\item{.init}{If supplied, will be used as the first value to start
the accumulation, rather than using \code{.x[[1]]}. This is useful if
you want to ensure that \code{reduce} returns a correct value when \code{.x}
is empty. If missing, and \code{.x} is empty, will throw an error.}
\item{.y}{For \code{reduce2()} and \code{accumulate2()}, an additional
argument that is passed to \code{.f}. If \code{init} is not set, \code{.y}
should be 1 element shorter than \code{.x}.}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
These functions were deprecated in purrr 0.3.0. Please use the
\code{.dir} argument of \code{\link[=reduce]{reduce()}} instead, or reverse your vectors
and use a left reduction.
}
\keyword{internal}
purrr/man/as_vector.Rd 0000644 0001762 0000144 00000002756 14330525021 014460 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/superseded-simplify.R
\name{as_vector}
\alias{as_vector}
\alias{simplify}
\alias{simplify_all}
\title{Coerce a list to a vector}
\usage{
as_vector(.x, .type = NULL)
simplify(.x, .type = NULL)
simplify_all(.x, .type = NULL)
}
\arguments{
\item{.x}{A list of vectors}
\item{.type}{Can be a vector mold specifying both the type and the
length of the vectors to be concatenated, such as \code{numeric(1)}
or \code{integer(4)}. Alternatively, it can be a string describing
the type, one of: "logical", "integer", "double", "complex",
"character" or "raw".}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
These functions were superseded in purrr 1.0.0 in favour of
\code{list_simplify()} which has more consistent semantics based on vctrs
principles:
\itemize{
\item \code{as_vector(x)} is now \code{list_simplify(x)}
\item \code{simplify(x)} is now \code{list_simplify(x, strict = FALSE)}
\item \code{simplify_all(x)} is \code{map(x, list_simplify, strict = FALSE)}
}
Superseded functions will not go away, but will only receive critical
bug fixes.
}
\examples{
# was
as.list(letters) |> as_vector("character")
# now
as.list(letters) |> list_simplify(ptype = character())
# was:
list(1:2, 3:4, 5:6) |> as_vector(integer(2))
# now:
list(1:2, 3:4, 5:6) |> list_c(ptype = integer())
}
\keyword{internal}
purrr/man/negate.Rd 0000644 0001762 0000144 00000002733 14311356421 013736 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/adverb-negate.R
\name{negate}
\alias{negate}
\title{Negate a predicate function so it selects what it previously rejected}
\usage{
negate(.p)
}
\arguments{
\item{.p}{A predicate function (i.e. a function that returns either \code{TRUE}
or \code{FALSE}) specified in one of the following ways:
\itemize{
\item A named function, e.g. \code{is.character}.
\item An anonymous function, e.g. \verb{\\(x) all(x < 0)} or \code{function(x) all(x < 0)}.
\item A formula, e.g. \code{~ all(.x < 0)}. You must use \code{.x} to refer to the first
argument). Only recommended if you require backward compatibility with
older versions of R.
}}
}
\value{
A new predicate function.
}
\description{
Negating a function changes \code{TRUE} to \code{FALSE} and \code{FALSE} to \code{TRUE}.
}
\section{Adverbs}{
This function is called an adverb because it modifies the effect of a
function (a verb). If you'd like to include a function created an adverb
in a package, be sure to read \link{faq-adverbs-export}.
}
\examples{
x <- list(x = 1:10, y = rbernoulli(10), z = letters)
x |> keep(is.numeric) |> names()
x |> keep(negate(is.numeric)) |> names()
# Same as
x |> discard(is.numeric)
}
\seealso{
Other adverbs:
\code{\link{auto_browse}()},
\code{\link{compose}()},
\code{\link{insistently}()},
\code{\link{partial}()},
\code{\link{possibly}()},
\code{\link{quietly}()},
\code{\link{safely}()},
\code{\link{slowly}()}
}
\concept{adverbs}
purrr/man/list_c.Rd 0000644 0001762 0000144 00000003665 14313364271 013761 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/list-combine.R
\name{list_c}
\alias{list_c}
\alias{list_cbind}
\alias{list_rbind}
\title{Combine list elements into a single data structure}
\usage{
list_c(x, ..., ptype = NULL)
list_cbind(
x,
...,
name_repair = c("unique", "universal", "check_unique"),
size = NULL
)
list_rbind(x, ..., names_to = rlang::zap(), ptype = NULL)
}
\arguments{
\item{x}{A list. For \code{list_rbind()} and \code{list_cbind()} the list must
only contain only data frames or \code{NULL}.}
\item{...}{These dots are for future extensions and must be empty.}
\item{ptype}{An optional prototype to ensure that the output type is always
the same.}
\item{name_repair}{One of \code{"unique"}, \code{"universal"}, or \code{"check_unique"}.
See \code{\link[vctrs:vec_as_names]{vctrs::vec_as_names()}} for the meaning of these options.}
\item{size}{An optional integer size to ensure that every input has the
same size (i.e. number of rows).}
\item{names_to}{By default, \code{names(x)} are lost. To keep them, supply a
string to \code{names_to} and the names will be saved into a column with that
name. If \code{names_to} is supplied and \code{x} is not named, the position of
the elements will be used instead of the names.}
}
\description{
\itemize{
\item \code{list_c()} combines elements into a vector by concatenating them together
with \code{\link[vctrs:vec_c]{vctrs::vec_c()}}.
\item \code{list_rbind()} combines elements into a data frame by row-binding them
together with \code{\link[vctrs:vec_bind]{vctrs::vec_rbind()}}.
\item \code{list_cbind()} combines elements into a data frame by column-binding them
together with \code{\link[vctrs:vec_bind]{vctrs::vec_cbind()}}.
}
}
\examples{
x1 <- list(a = 1, b = 2, c = 3)
list_c(x1)
x2 <- list(
a = data.frame(x = 1:2),
b = data.frame(y = "a")
)
list_rbind(x2)
list_rbind(x2, names_to = "id")
list_rbind(unname(x2), names_to = "id")
list_cbind(x2)
}
purrr/man/invoke.Rd 0000644 0001762 0000144 00000006524 14311356421 013770 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-invoke.R
\name{invoke}
\alias{invoke}
\alias{invoke_map}
\alias{invoke_map_lgl}
\alias{invoke_map_int}
\alias{invoke_map_dbl}
\alias{invoke_map_chr}
\alias{invoke_map_raw}
\alias{invoke_map_dfr}
\alias{invoke_map_dfc}
\alias{invoke_map_df}
\title{Invoke functions.}
\usage{
invoke(.f, .x = NULL, ..., .env = NULL)
invoke_map(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_lgl(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_int(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_dbl(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_chr(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_raw(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_dfr(.f, .x = list(NULL), ..., .env = NULL)
invoke_map_dfc(.f, .x = list(NULL), ..., .env = NULL)
}
\arguments{
\item{.f}{For \code{invoke}, a function; for \code{invoke_map} a
list of functions.}
\item{.x}{For \code{invoke}, an argument-list; for \code{invoke_map} a
list of argument-lists the same length as \code{.f} (or length 1).
The default argument, \code{list(NULL)}, will be recycled to the
same length as \code{.f}, and will call each function with no
arguments (apart from any supplied in \code{...}.}
\item{...}{Additional arguments passed to each function.}
\item{.env}{Environment in which \code{\link[=do.call]{do.call()}} should
evaluate a constructed expression. This only matters if you pass
as \code{.f} the name of a function rather than its value, or as
\code{.x} symbols of objects rather than their values.}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
These functions were superded in purrr 0.3.0 and deprecated in purrr 1.0.0.
\itemize{
\item \code{invoke()} is deprecated in favour of the simpler \code{exec()} function
reexported from rlang. \code{exec()} evaluates a function call built
from its inputs and supports \link[rlang:dyn-dots]{dynamic dots}:
\if{html}{\out{
}}\preformatted{# Before:
invoke(mean, list(na.rm = TRUE), x = 1:10)
# After
exec(mean, 1:10, !!!list(na.rm = TRUE))
}\if{html}{\out{
}}
\item \code{invoke_map()} is deprecated because it's harder to understand than the
corresponding code using \code{map()}/\code{map2()} and \code{exec()}:
\if{html}{\out{
}}
}
}
\examples{
# was
invoke(runif, list(n = 10))
invoke(runif, n = 10)
# now
exec(runif, n = 10)
# was
args <- list("01a", "01b")
invoke(paste, args, sep = "-")
# now
exec(paste, !!!args, sep = "-")
# was
funs <- list(runif, rnorm)
funs |> invoke_map(n = 5)
funs |> invoke_map(list(list(n = 10), list(n = 5)))
# now
funs |> map(exec, n = 5)
funs |> map2(list(list(n = 10), list(n = 5)), function(f, args) exec(f, !!!args))
# or use pmap + a tibble
df <- tibble::tibble(
fun = list(runif, rnorm),
args = list(list(n = 10), list(n = 5))
)
df |> pmap(function(fun, args) exec(fun, !!!args))
# was
list(m1 = mean, m2 = median) |> invoke_map(x = rcauchy(100))
# now
list(m1 = mean, m2 = median) |> map(function(f) f(rcauchy(100)))
}
\keyword{internal}
purrr/man/keep_at.Rd 0000644 0001762 0000144 00000002240 14311066210 014066 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/keep.R
\name{keep_at}
\alias{keep_at}
\alias{discard_at}
\title{Keep/discard elements based on their name/position}
\usage{
keep_at(x, at)
discard_at(x, at)
}
\arguments{
\item{x}{A list or atomic vector.}
\item{at}{A logical, integer, or character vector giving the elements
to select. Alternatively, a function that takes a vector of names,
and returns a logical, integer, or character vector of elements to select.
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}: if the tidyselect package is
installed, you can use \code{vars()} and tidyselect helpers to select
elements.}
}
\description{
Keep/discard elements based on their name/position
}
\examples{
x <- c(a = 1, b = 2, cat = 10, dog = 15, elephant = 5, e = 10)
x \%>\% keep_at(letters)
x \%>\% discard_at(letters)
# Can also use a function
x \%>\% keep_at(~ nchar(.x) == 3)
x \%>\% discard_at(~ nchar(.x) == 3)
}
\seealso{
\code{\link[=keep]{keep()}}/\code{\link[=discard]{discard()}} to keep/discard elements by value.
}
purrr/man/splice.Rd 0000644 0001762 0000144 00000002102 14311356421 013740 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-splice.R
\name{splice}
\alias{splice}
\title{Splice objects and lists of objects into a list}
\usage{
splice(...)
}
\arguments{
\item{...}{Objects to concatenate.}
}
\value{
A list.
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
This function was deprecated in purrr 1.0.0 because we no longer believe that
this style of implicit/automatic splicing is a good idea; instead use
\code{rlang::list2()} + \verb{!!!} or \code{\link[=list_flatten]{list_flatten()}}.
\code{splice()} splices all arguments into a list. Non-list objects and lists
with a S3 class are encapsulated in a list before concatenation.
}
\examples{
inputs <- list(arg1 = "a", arg2 = "b")
# splice() concatenates the elements of inputs with arg3
splice(inputs, arg3 = c("c1", "c2")) |> str()
list(inputs, arg3 = c("c1", "c2")) |> str()
c(inputs, arg3 = c("c1", "c2")) |> str()
}
\keyword{internal}
purrr/man/map_raw.Rd 0000644 0001762 0000144 00000001561 14310436312 014114 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/map-raw.R
\name{map_raw}
\alias{map_raw}
\alias{map2_raw}
\alias{imap_raw}
\alias{pmap_raw}
\alias{flatten_raw}
\title{Functions that return raw vectors}
\usage{
map_raw(.x, .f, ...)
map2_raw(.x, .y, .f, ...)
imap_raw(.x, .f, ...)
pmap_raw(.l, .f, ...)
flatten_raw(.x)
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
These functions were deprecated in purrr 1.0.0 because they are of limited
use and you can now use \code{map_vec()} instead. They are variants of \code{\link[=map]{map()}},
\code{\link[=map2]{map2()}}, \code{\link[=imap]{imap()}}, \code{\link[=pmap]{pmap()}}, and \code{\link[=flatten]{flatten()}} that return raw vectors.
}
\keyword{internal}
purrr/man/purrr-package.Rd 0000644 0001762 0000144 00000001551 14355607005 015240 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/package-purrr.R
\docType{package}
\name{purrr-package}
\alias{purrr}
\alias{purrr-package}
\title{purrr: Functional Programming Tools}
\description{
\if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}
A complete and consistent functional programming toolkit for R.
}
\seealso{
Useful links:
\itemize{
\item \url{https://purrr.tidyverse.org/}
\item \url{https://github.com/tidyverse/purrr}
\item Report bugs at \url{https://github.com/tidyverse/purrr/issues}
}
}
\author{
\strong{Maintainer}: Hadley Wickham \email{hadley@rstudio.com} (\href{https://orcid.org/0000-0003-4757-117X}{ORCID})
Authors:
\itemize{
\item Lionel Henry \email{lionel@rstudio.com}
}
Other contributors:
\itemize{
\item RStudio [copyright holder, funder]
}
}
\keyword{internal}
purrr/man/at_depth.Rd 0000644 0001762 0000144 00000000656 14326047453 014275 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-map.R
\name{at_depth}
\alias{at_depth}
\title{Map at depth}
\usage{
at_depth(.x, .depth, .f, ...)
}
\description{
This function is defunct and has been replaced by \code{\link[=map_depth]{map_depth()}}.
See also \code{\link[=modify_depth]{modify_depth()}} for a version that preserves the types of
the elements of the tree.
}
\keyword{internal}
purrr/man/along.Rd 0000644 0001762 0000144 00000001500 14310436312 013557 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-along.R
\name{along}
\alias{along}
\alias{list_along}
\title{Create a list of given length}
\usage{
list_along(x)
}
\arguments{
\item{x}{A vector.}
}
\value{
A list of the same length as \code{x}.
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
This function was deprecated in purrr 1.0.0 since it's not related to the
core purpose of purrr.
It can be useful to create an empty list that you plan to fill later. This is
similar to the idea of \code{\link[=seq_along]{seq_along()}}, which creates a vector of the same
length as its input.
}
\examples{
x <- 1:5
seq_along(x)
list_along(x)
}
\keyword{internal}
purrr/man/rdunif.Rd 0000644 0001762 0000144 00000001263 14311066210 013751 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-utils.R
\name{rdunif}
\alias{rdunif}
\title{Generate random sample from a discrete uniform distribution}
\usage{
rdunif(n, b, a = 1)
}
\arguments{
\item{n}{Number of samples to draw.}
\item{a, b}{Range of the distribution (inclusive).}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
This function was deprecated in purrr 1.0.0 because it's not related to the
core purpose of purrr.
}
\examples{
table(rdunif(1e3, 10))
table(rdunif(1e3, 10, -5))
}
\keyword{internal}
purrr/man/map.Rd 0000644 0001762 0000144 00000013365 14460311734 013256 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/map.R
\name{map}
\alias{map}
\alias{map_lgl}
\alias{map_int}
\alias{map_dbl}
\alias{map_chr}
\alias{map_vec}
\alias{walk}
\title{Apply a function to each element of a vector}
\usage{
map(.x, .f, ..., .progress = FALSE)
map_lgl(.x, .f, ..., .progress = FALSE)
map_int(.x, .f, ..., .progress = FALSE)
map_dbl(.x, .f, ..., .progress = FALSE)
map_chr(.x, .f, ..., .progress = FALSE)
map_vec(.x, .f, ..., .ptype = NULL, .progress = FALSE)
walk(.x, .f, ..., .progress = FALSE)
}
\arguments{
\item{.x}{A list or atomic vector.}
\item{.f}{A function, specified in one of the following ways:
\itemize{
\item A named function, e.g. \code{mean}.
\item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
\item A formula, e.g. \code{~ .x + 1}. You must use \code{.x} to refer to the first
argument. Only recommended if you require backward compatibility with
older versions of R.
\item A string, integer, or list, e.g. \code{"idx"}, \code{1}, or \code{list("idx", 1)} which
are shorthand for \verb{\\(x) pluck(x, "idx")}, \verb{\\(x) pluck(x, 1)}, and
\verb{\\(x) pluck(x, "idx", 1)} respectively. Optionally supply \code{.default} to
set a default value if the indexed element is \code{NULL} or does not exist.
}}
\item{...}{Additional arguments passed on to the mapped function.
We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
\if{html}{\out{
}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{
}}
This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}
\item{.progress}{Whether to show a progress bar. Use \code{TRUE} to turn on
a basic progress bar, use a string to give it a name, or see
\link{progress_bars} for more details.}
\item{.ptype}{If \code{NULL}, the default, the output type is the common type
of the elements of the result. Otherwise, supply a "prototype" giving
the desired type of output.}
}
\value{
The output length is determined by the length of the input.
The output names are determined by the input names.
The output type is determined by the suffix:
\itemize{
\item No suffix: a list; \code{.f()} can return anything.
\item \verb{_lgl()}, \verb{_int()}, \verb{_dbl()}, \verb{_chr()} return a logical, integer, double,
or character vector respectively; \code{.f()} must return a compatible atomic
vector of length 1.
\item \verb{_vec()} return an atomic or S3 vector, the same type that \code{.f} returns.
\code{.f} can return pretty much any type of vector, as long as its length 1.
\item \code{walk()} returns the input \code{.x} (invisibly). This makes it easy to
use in a pipe. The return value of \code{.f()} is ignored.
}
Any errors thrown by \code{.f} will be wrapped in an error with class
\link{purrr_error_indexed}.
}
\description{
The map functions transform their input by applying a function to
each element of a list or atomic vector and returning an object of
the same length as the input.
\itemize{
\item \code{map()} always returns a list. See the \code{\link[=modify]{modify()}} family for
versions that return an object of the same type as the input.
\item \code{map_lgl()}, \code{map_int()}, \code{map_dbl()} and \code{map_chr()} return an
atomic vector of the indicated type (or die trying). For these functions,
\code{.f} must return a length-1 vector of the appropriate type.
\item \code{map_vec()} simplifies to the common type of the output. It works with
most types of simple vectors like Date, POSIXct, factors, etc.
\item \code{walk()} calls \code{.f} for its side-effect and returns
the input \code{.x}.
}
}
\examples{
# Compute normal distributions from an atomic vector
1:10 |>
map(rnorm, n = 10)
# You can also use an anonymous function
1:10 |>
map(\(x) rnorm(10, x))
# Simplify output to a vector instead of a list by computing the mean of the distributions
1:10 |>
map(rnorm, n = 10) |> # output a list
map_dbl(mean) # output an atomic vector
# Using set_names() with character vectors is handy to keep track
# of the original inputs:
set_names(c("foo", "bar")) |> map_chr(paste0, ":suffix")
# Working with lists
favorite_desserts <- list(Sophia = "banana bread", Eliott = "pancakes", Karina = "chocolate cake")
favorite_desserts |> map_chr(\(food) paste(food, "rocks!"))
# Extract by name or position
# .default specifies value for elements that are missing or NULL
l1 <- list(list(a = 1L), list(a = NULL, b = 2L), list(b = 3L))
l1 |> map("a", .default = "???")
l1 |> map_int("b", .default = NA)
l1 |> map_int(2, .default = NA)
# Supply multiple values to index deeply into a list
l2 <- list(
list(num = 1:3, letters[1:3]),
list(num = 101:103, letters[4:6]),
list()
)
l2 |> map(c(2, 2))
# Use a list to build an extractor that mixes numeric indices and names,
# and .default to provide a default value if the element does not exist
l2 |> map(list("num", 3))
l2 |> map_int(list("num", 3), .default = NA)
# Working with data frames
# Use map_lgl(), map_dbl(), etc to return a vector instead of a list:
mtcars |> map_dbl(sum)
# A more realistic example: split a data frame into pieces, fit a
# model to each piece, summarise and extract R^2
mtcars |>
split(mtcars$cyl) |>
map(\(df) lm(mpg ~ wt, data = df)) |>
map(summary) |>
map_dbl("r.squared")
}
\seealso{
\code{\link[=map_if]{map_if()}} for applying a function to only those elements
of \code{.x} that meet a specified condition.
Other map variants:
\code{\link{imap}()},
\code{\link{lmap}()},
\code{\link{map2}()},
\code{\link{map_depth}()},
\code{\link{map_if}()},
\code{\link{modify}()},
\code{\link{pmap}()}
}
\concept{map variants}
purrr/man/every.Rd 0000644 0001762 0000144 00000003115 14311356421 013620 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/every-some-none.R
\name{every}
\alias{every}
\alias{some}
\alias{none}
\title{Do every, some, or none of the elements of a list satisfy a predicate?}
\usage{
every(.x, .p, ...)
some(.x, .p, ...)
none(.x, .p, ...)
}
\arguments{
\item{.x}{A list or vector.}
\item{.p}{A predicate function (i.e. a function that returns either \code{TRUE}
or \code{FALSE}) specified in one of the following ways:
\itemize{
\item A named function, e.g. \code{is.character}.
\item An anonymous function, e.g. \verb{\\(x) all(x < 0)} or \code{function(x) all(x < 0)}.
\item A formula, e.g. \code{~ all(.x < 0)}. You must use \code{.x} to refer to the first
argument). Only recommended if you require backward compatibility with
older versions of R.
}}
\item{...}{Additional arguments passed on to \code{.p}.}
}
\value{
A logical vector of length 1.
}
\description{
\itemize{
\item \code{some()} returns \code{TRUE} when \code{.p} is \code{TRUE} for at least one element.
\item \code{every()} returns \code{TRUE} when \code{.p} is \code{TRUE} for all elements.
\item \code{none()} returns \code{TRUE} when \code{.p} is \code{FALSE} for all elements.
}
}
\examples{
x <- list(0:10, 5.5)
x |> every(is.numeric)
x |> every(is.integer)
x |> some(is.integer)
x |> none(is.character)
# Missing values are propagated:
some(list(NA, FALSE), identity)
# If you need to use these functions in a context where missing values are
# unsafe (e.g. in `if ()` conditions), make sure to use safe predicates:
if (some(list(NA, FALSE), rlang::is_true)) "foo" else "bar"
}
purrr/man/transpose.Rd 0000644 0001762 0000144 00000005115 14330525021 014501 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/superseded-transpose.R
\name{transpose}
\alias{transpose}
\title{Transpose a list.}
\usage{
transpose(.l, .names = NULL)
}
\arguments{
\item{.l}{A list of vectors to transpose. The first element is used as the
template; you'll get a warning if a subsequent element has a different
length.}
\item{.names}{For efficiency, \code{transpose()} bases the return structure on
the first component of \code{.l} by default. Specify \code{.names} to override this.}
}
\value{
A list with indexing transposed compared to \code{.l}.
\code{transpose()} is its own inverse, much like the transpose operation on a
matrix. You can get back the original input by transposing it twice.
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
\code{transpose()} turns a list-of-lists "inside-out"; it turns a pair of lists
into a list of pairs, or a list of pairs into pair of lists. For example,
if you had a list of length n where each component had values \code{a} and
\code{b}, \code{transpose()} would make a list with elements \code{a} and
\code{b} that contained lists of length n. It's called transpose because
\code{x[[1]][[2]]} is equivalent to \code{transpose(x)[[2]][[1]]}.
This function was superseded in purrr 1.0.0 because \code{\link[=list_transpose]{list_transpose()}}
has a better name and can automatically simplify the output, as is commonly
needed. Superseded functions will not go away, but will only receive critical
bug fixes.
}
\examples{
x <- map(1:5, \(i) list(x = runif(1), y = runif(5)))
# was
x |> transpose() |> str()
# now
x |> list_transpose(simplify = FALSE) |> str()
# transpose() is useful in conjunction with safely() & quietly()
x <- list("a", 1, 2)
y <- x |> map(safely(log))
# was
y |> transpose() |> str()
# now:
y |> list_transpose() |> str()
# Previously, output simplification required a call to another function
x <- list(list(a = 1, b = 2), list(a = 3, b = 4), list(a = 5, b = 6))
x |> transpose() |> simplify_all()
# Now can take advantage of automatic simplification
x |> list_transpose()
# Provide explicit component names to prevent loss of those that don't
# appear in first component
ll <- list(
list(x = 1, y = "one"),
list(z = "deux", x = 2)
)
ll |> transpose()
nms <- ll |> map(names) |> reduce(union)
# was
ll |> transpose(.names = nms)
# now
ll |> list_transpose(template = nms)
# and can supply default value
ll |> list_transpose(template = nms, default = NA)
}
\keyword{internal}
purrr/man/rbernoulli.Rd 0000644 0001762 0000144 00000001264 14311066210 014640 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-utils.R
\name{rbernoulli}
\alias{rbernoulli}
\title{Generate random sample from a Bernoulli distribution}
\usage{
rbernoulli(n, p = 0.5)
}
\arguments{
\item{n}{Number of samples}
\item{p}{Probability of getting \code{TRUE}}
}
\value{
A logical vector
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
This function was deprecated in purrr 1.0.0 because it's not related to the
core purpose of purrr.
}
\examples{
rbernoulli(10)
rbernoulli(100, 0.1)
}
\keyword{internal}
purrr/man/pluck_depth.Rd 0000644 0001762 0000144 00000001365 14315046000 014766 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/pluck-depth.R
\name{pluck_depth}
\alias{pluck_depth}
\alias{vec_depth}
\title{Compute the depth of a vector}
\usage{
pluck_depth(x, is_node = NULL)
}
\arguments{
\item{x}{A vector}
\item{is_node}{Optionally override the default criteria for determine an
element can be recursed within. The default matches the behaviour of
\code{pluck()} which can recurse into lists and expressions.}
}
\value{
An integer.
}
\description{
The depth of a vector is how many levels that you can index/pluck into it.
\code{pluck_depth()} was previously called \code{vec_depth()}.
}
\examples{
x <- list(
list(),
list(list()),
list(list(list(1)))
)
pluck_depth(x)
x |> map_int(pluck_depth)
}
purrr/man/when.Rd 0000644 0001762 0000144 00000003346 14355573665 013460 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-when.R
\name{when}
\alias{when}
\title{Match/validate a set of conditions for an object and continue with the action
associated with the first valid match.}
\usage{
when(., ...)
}
\arguments{
\item{.}{the value to match against}
\item{...}{formulas; each containing a condition as LHS and an action as RHS.
named arguments will define additional values.}
}
\value{
The value resulting from the action of the first valid
match/condition is returned. If no matches are found, and no default is
given, NULL will be returned.
Validity of the conditions are tested with \code{isTRUE}, or equivalently
with \code{identical(condition, TRUE)}.
In other words conditions resulting in more than one logical will never
be valid. Note that the input value is always treated as a single object,
as opposed to the \code{ifelse} function.
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
This function was deprecated in purrr 1.0.0 because it's not related to the
core purpose of purrr. You can pull your code out of a pipe and use regular
\code{if}/\verb{else} statements instead.
\code{when()} is a flavour of pattern matching (or an if-else abstraction) in
which a value is matched against a sequence of condition-action sets. When a
valid match/condition is found the action is executed and the result of the
action is returned.
}
\examples{
1:10 \%>\%
when(
sum(.) <= 50 ~ sum(.),
sum(.) <= 100 ~ sum(.)/2,
~ 0
)
# now
x <- 1:10
if (sum(x) < 10) {
sum(x)
} else if (sum(x) < 100) {
sum(x) / 2
} else {
0
}
}
\keyword{internal}
purrr/man/get-attr.Rd 0000644 0001762 0000144 00000001252 14311066210 014207 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/deprec-utils.R
\name{get-attr}
\alias{get-attr}
\alias{\%@\%}
\title{Infix attribute accessor}
\usage{
x \%@\% name
}
\arguments{
\item{x}{Object}
\item{name}{Attribute name}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
This function was deprecated in purrr 0.3.0. Instead, lease use the \verb{\%@\%}
operator exported in rlang. It has an interface more consistent with \code{@}:
uses NSE, supports S4 fields, and has an assignment variant.
}
\keyword{internal}
purrr/man/pluck.Rd 0000644 0001762 0000144 00000007352 14347636610 013625 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/pluck.R
\name{pluck}
\alias{pluck}
\alias{pluck<-}
\alias{pluck_exists}
\title{Safely get or set an element deep within a nested data structure}
\usage{
pluck(.x, ..., .default = NULL)
pluck(.x, ...) <- value
pluck_exists(.x, ...)
}
\arguments{
\item{.x, x}{A vector or environment}
\item{...}{A list of accessors for indexing into the object. Can be
an positive integer, a negative integer (to index from the right),
a string (to index into names), or an accessor function
(except for the assignment variants which only support names and
positions). If the object being indexed is an S4 object,
accessing it by name will return the corresponding slot.
\link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if
your accessors are stored in a list, you can splice that in with
\verb{!!!}.}
\item{.default}{Value to use if target is \code{NULL} or absent.}
\item{value}{A value to replace in \code{.x} at the pluck location.
Use \code{zap()} to instead remove the element.}
}
\description{
\code{pluck()} implements a generalised form of \code{[[} that allow you to index
deeply and flexibly into data structures. It always succeeds, returning
\code{.default} if the index you are trying to access does not exist or is \code{NULL}.
\verb{pluck<-()} is the assignment equivalent, allowing you to modify an object
deep within a nested data structure.
\code{pluck_exists()} tells you whether or not an object exists using the
same rules as pluck (i.e. a \code{NULL} element is equivalent to an absent
element).
}
\details{
\itemize{
\item You can pluck or chuck with standard accessors like integer
positions and string names, and also accepts arbitrary accessor
functions, i.e. functions that take an object and return some
internal piece.
This is often more readable than a mix of operators and accessors
because it reads linearly and is free of syntactic
cruft. Compare: \code{accessor(x[[1]])$foo} to \code{pluck(x, 1, accessor, "foo")}.
\item These accessors never partial-match. This is unlike \code{$} which
will select the \code{disp} object if you write \code{mtcars$di}.
}
}
\examples{
# Let's create a list of data structures:
obj1 <- list("a", list(1, elt = "foo"))
obj2 <- list("b", list(2, elt = "bar"))
x <- list(obj1, obj2)
# pluck() provides a way of retrieving objects from such data
# structures using a combination of numeric positions, vector or
# list names, and accessor functions.
# Numeric positions index into the list by position, just like `[[`:
pluck(x, 1)
# same as x[[1]]
# Index from the back
pluck(x, -1)
# same as x[[2]]
pluck(x, 1, 2)
# same as x[[1]][[2]]
# Supply names to index into named vectors:
pluck(x, 1, 2, "elt")
# same as x[[1]][[2]][["elt"]]
# By default, pluck() consistently returns `NULL` when an element
# does not exist:
pluck(x, 10)
try(x[[10]])
# You can also supply a default value for non-existing elements:
pluck(x, 10, .default = NA)
# The map() functions use pluck() by default to retrieve multiple
# values from a list:
map_chr(x, 1)
map_int(x, c(2, 1))
# pluck() also supports accessor functions:
my_element <- function(x) x[[2]]$elt
pluck(x, 1, my_element)
pluck(x, 2, my_element)
# Even for this simple data structure, this is more readable than
# the alternative form because it requires you to read both from
# right-to-left and from left-to-right in different parts of the
# expression:
my_element(x[[1]])
# If you have a list of accessors, you can splice those in with `!!!`:
idx <- list(1, my_element)
pluck(x, !!!idx)
}
\seealso{
\code{\link[=attr_getter]{attr_getter()}} for creating attribute getters suitable
for use with \code{pluck()} and \code{chuck()}. \code{\link[=modify_in]{modify_in()}} for
applying a function to a pluck location.
}
purrr/man/update_list.Rd 0000644 0001762 0000144 00000002301 14310436312 014774 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/list-modify.R
\name{update_list}
\alias{update_list}
\title{Update a list with formulas}
\usage{
update_list(.x, ...)
}
\arguments{
\item{.x}{List to modify.}
\item{...}{New values of a list. Use \code{zap()} to remove values.
These values should be either all named or all unnamed. When
inputs are all named, they are matched to \code{.x} by name. When they
are all unnamed, they are matched by position.
\link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if your
replacement values are stored in a list, you can splice that in with
\verb{!!!}.}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
\code{update_list()} was deprecated in purrr 1.0.0, because we no longer believe
that functions that use NSE are a good fit for purrr.
\code{update_list()} handles formulas and quosures that can refer to
values existing within the input list. This function is deprecated
because we no longer believe that functions that use tidy evaluation are
a good fit for purrr.
}
\keyword{internal}
purrr/man/has_element.Rd 0000644 0001762 0000144 00000000623 14311356421 014753 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/detect.R
\name{has_element}
\alias{has_element}
\title{Does a list contain an object?}
\usage{
has_element(.x, .y)
}
\arguments{
\item{.x}{A list or atomic vector.}
\item{.y}{Object to test for}
}
\description{
Does a list contain an object?
}
\examples{
x <- list(1:10, 5, 9.9)
x |> has_element(1:10)
x |> has_element(3)
}
purrr/man/list_flatten.Rd 0000644 0001762 0000144 00000003476 14313364271 015174 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/list-flatten.R
\name{list_flatten}
\alias{list_flatten}
\title{Flatten a list}
\usage{
list_flatten(
x,
...,
name_spec = "{outer}_{inner}",
name_repair = c("minimal", "unique", "check_unique", "universal")
)
}
\arguments{
\item{x}{A list.}
\item{...}{These dots are for future extensions and must be empty.}
\item{name_spec}{If both inner and outer names are present, control
how they are combined. Should be a glue specification that uses
variables \code{inner} and \code{outer}.}
\item{name_repair}{One of \code{"minimal"}, \code{"unique"}, \code{"universal"}, or
\code{"check_unique"}. See \code{\link[vctrs:vec_as_names]{vctrs::vec_as_names()}} for the meaning of these
options.}
}
\value{
A list of the same type as \code{x}. The list might be shorter
if \code{x} contains empty lists, the same length if it contains lists
of length 1 or no sub-lists, or longer if it contains lists of
length > 1.
}
\description{
Flattening a list removes a single layer of internal hierarchy,
i.e. it inlines elements that are lists leaving non-lists alone.
}
\examples{
x <- list(1, list(2, 3), list(4, list(5)))
x |> list_flatten() |> str()
x |> list_flatten() |> list_flatten() |> str()
# Flat lists are left as is
list(1, 2, 3, 4, 5) |> list_flatten() |> str()
# Empty lists will disappear
list(1, list(), 2, list(3)) |> list_flatten() |> str()
# Another way to see this is that it reduces the depth of the list
x <- list(
list(),
list(list())
)
x |> pluck_depth()
x |> list_flatten() |> pluck_depth()
# Use name_spec to control how inner and outer names are combined
x <- list(x = list(a = 1, b = 2), y = list(c = 1, d = 2))
x |> list_flatten() |> names()
x |> list_flatten(name_spec = "{outer}") |> names()
x |> list_flatten(name_spec = "{inner}") |> names()
}
purrr/man/compose.Rd 0000644 0001762 0000144 00000003322 14311356421 014133 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/adverb-compose.R
\name{compose}
\alias{compose}
\title{Compose multiple functions together to create a new function}
\usage{
compose(..., .dir = c("backward", "forward"))
}
\arguments{
\item{...}{Functions to apply in order (from right to left by
default). Formulas are converted to functions in the usual way.
\link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if
your functions are stored in a list, you can splice that in with
\verb{!!!}.}
\item{.dir}{If \code{"backward"} (the default), the functions are called
in the reverse order, from right to left, as is conventional in
mathematics. If \code{"forward"}, they are called from left to right.}
}
\value{
A function
}
\description{
Create a new function that is the composition of multiple functions,
i.e. \code{compose(f, g)} is equivalent to \code{function(...) f(g(...))}.
}
\section{Adverbs}{
This function is called an adverb because it modifies the effect of a
function (a verb). If you'd like to include a function created an adverb
in a package, be sure to read \link{faq-adverbs-export}.
}
\examples{
not_null <- compose(`!`, is.null)
not_null(4)
not_null(NULL)
add1 <- function(x) x + 1
compose(add1, add1)(8)
fn <- compose(\(x) paste(x, "foo"), \(x) paste(x, "bar"))
fn("input")
# Lists of functions can be spliced with !!!
fns <- list(
function(x) paste(x, "foo"),
\(x) paste(x, "bar")
)
fn <- compose(!!!fns)
fn("input")
}
\seealso{
Other adverbs:
\code{\link{auto_browse}()},
\code{\link{insistently}()},
\code{\link{negate}()},
\code{\link{partial}()},
\code{\link{possibly}()},
\code{\link{quietly}()},
\code{\link{safely}()},
\code{\link{slowly}()}
}
\concept{adverbs}
purrr/man/lmap.Rd 0000644 0001762 0000144 00000006471 14314671330 013431 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/lmap.R
\name{lmap}
\alias{lmap}
\alias{lmap_if}
\alias{lmap_at}
\title{Apply a function to list-elements of a list}
\usage{
lmap(.x, .f, ...)
lmap_if(.x, .p, .f, ..., .else = NULL)
lmap_at(.x, .at, .f, ...)
}
\arguments{
\item{.x}{A list or data frame.}
\item{.f}{A function that takes a length-1 list and returns a list (of any
length.)}
\item{...}{Additional arguments passed on to the mapped function.
We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
\if{html}{\out{
}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{
}}
This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}
\item{.p}{A single predicate function, a formula describing such a
predicate function, or a logical vector of the same length as \code{.x}.
Alternatively, if the elements of \code{.x} are themselves lists of
objects, a string indicating the name of a logical element in the
inner lists. Only those elements where \code{.p} evaluates to
\code{TRUE} will be modified.}
\item{.else}{A function applied to elements of \code{.x} for which \code{.p}
returns \code{FALSE}.}
\item{.at}{A logical, integer, or character vector giving the elements
to select. Alternatively, a function that takes a vector of names,
and returns a logical, integer, or character vector of elements to select.
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}: if the tidyselect package is
installed, you can use \code{vars()} and tidyselect helpers to select
elements.}
}
\value{
A list or data frame, matching \code{.x}. There are no guarantees about
the length.
}
\description{
\code{lmap()}, \code{lmap_at()} and \code{lmap_if()} are similar to \code{map()}, \code{map_at()} and
\code{map_if()}, except instead of mapping over \code{.x[[i]]}, they instead map over
\code{.x[i]}.
This has several advantages:
\itemize{
\item It makes it possible to work with functions that exclusively take a list.
\item It allows \code{.f} to access the attributes of the encapsulating list,
like \code{\link[=names]{names()}}.
\item It allows \code{.f} to return a larger or small list than it receives
changing the size of the output.
}
}
\examples{
set.seed(1014)
# Let's write a function that returns a larger list or an empty list
# depending on some condition. It also uses the input name to name the
# output
maybe_rep <- function(x) {
n <- rpois(1, 2)
set_names(rep_len(x, n), paste0(names(x), seq_len(n)))
}
# The output size varies each time we map f()
x <- list(a = 1:4, b = letters[5:7], c = 8:9, d = letters[10])
x |> lmap(maybe_rep) |> str()
# We can apply f() on a selected subset of x
x |> lmap_at(c("a", "d"), maybe_rep) |> str()
# Or only where a condition is satisfied
x |> lmap_if(is.character, maybe_rep) |> str()
}
\seealso{
Other map variants:
\code{\link{imap}()},
\code{\link{map2}()},
\code{\link{map_depth}()},
\code{\link{map_if}()},
\code{\link{map}()},
\code{\link{modify}()},
\code{\link{pmap}()}
}
\concept{map variants}
purrr/man/map_dfr.Rd 0000644 0001762 0000144 00000005421 14330525021 014073 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/superseded-map-df.R
\name{map_dfr}
\alias{map_dfr}
\alias{map_df}
\alias{map_dfc}
\alias{imap_dfr}
\alias{imap_dfc}
\alias{map2_dfr}
\alias{map2_dfc}
\alias{map2_df}
\alias{pmap_dfr}
\alias{pmap_dfc}
\alias{pmap_df}
\title{Functions that return data frames}
\usage{
map_dfr(.x, .f, ..., .id = NULL)
map_dfc(.x, .f, ...)
imap_dfr(.x, .f, ..., .id = NULL)
imap_dfc(.x, .f, ...)
map2_dfr(.x, .y, .f, ..., .id = NULL)
map2_dfc(.x, .y, .f, ...)
pmap_dfr(.l, .f, ..., .id = NULL)
pmap_dfc(.l, .f, ...)
}
\arguments{
\item{.id}{Either a string or \code{NULL}. If a string, the output will contain
a variable with that name, storing either the name (if \code{.x} is named) or
the index (if \code{.x} is unnamed) of the input. If \code{NULL}, the default, no
variable will be created.
Only applies to \verb{_dfr} variant.}
}
\description{
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
These \code{\link[=map]{map()}}, \code{\link[=map2]{map2()}}, \code{\link[=imap]{imap()}}, and \code{\link[=pmap]{pmap()}} variants return data
frames by row-binding or column-binding the outputs together.
The functions were superseded in purrr 1.0.0 because their names
suggest they work like \verb{_lgl()}, \verb{_int()}, etc which require length
1 outputs, but actually they return results of any size because the results
are combined without any size checks. Additionally, they use
\code{dplyr::bind_rows()} and \code{dplyr::bind_cols()} which require dplyr to be
installed and have confusing semantics with edge cases. Superseded
functions will not go away, but will only receive critical bug fixes.
Instead, we recommend using \code{map()}, \code{map2()}, etc with \code{\link[=list_rbind]{list_rbind()}} and
\code{\link[=list_cbind]{list_cbind()}}. These use \code{\link[vctrs:vec_bind]{vctrs::vec_rbind()}} and \code{\link[vctrs:vec_bind]{vctrs::vec_cbind()}}
under the hood, and have names that more clearly reflect their semantics.
}
\examples{
# map ---------------------------------------------
# Was:
mtcars |>
split(mtcars$cyl) |>
map(\(df) lm(mpg ~ wt, data = df)) |>
map_dfr(\(mod) as.data.frame(t(as.matrix(coef(mod)))))
# Now:
mtcars |>
split(mtcars$cyl) |>
map(\(df) lm(mpg ~ wt, data = df)) |>
map(\(mod) as.data.frame(t(as.matrix(coef(mod))))) |>
list_rbind()
# map2 ---------------------------------------------
ex_fun <- function(arg1, arg2){
col <- arg1 + arg2
x <- as.data.frame(col)
}
arg1 <- 1:4
arg2 <- 10:13
# was
map2_dfr(arg1, arg2, ex_fun)
# now
map2(arg1, arg2, ex_fun) |> list_rbind()
# was
map2_dfc(arg1, arg2, ex_fun)
# now
map2(arg1, arg2, ex_fun) |> list_cbind()
}
\keyword{internal}
purrr/man/safely.Rd 0000644 0001762 0000144 00000003767 14355342401 013767 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/adverb-safely.R
\name{safely}
\alias{safely}
\title{Wrap a function to capture errors}
\usage{
safely(.f, otherwise = NULL, quiet = TRUE)
}
\arguments{
\item{.f}{A function to modify, specified in one of the following ways:
\itemize{
\item A named function, e.g. \code{mean}.
\item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
\item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
compatibility with older versions of R.
}}
\item{otherwise}{Default value to use when an error occurs.}
\item{quiet}{Hide errors (\code{TRUE}, the default), or display them
as they occur?}
}
\value{
A function that takes the same arguments as \code{.f}, but returns
a different value, as described above.
}
\description{
Creates a modified version of \code{.f} that always succeeds. It returns a list
with components \code{result} and \code{error}. If the function succeeds, \code{result}
contains the returned value and \code{error} is \code{NULL}. If an error occurred,
\code{error} is an \code{error} object and \code{result} is either \code{NULL} or \code{otherwise}.
}
\section{Adverbs}{
This function is called an adverb because it modifies the effect of a
function (a verb). If you'd like to include a function created an adverb
in a package, be sure to read \link{faq-adverbs-export}.
}
\examples{
safe_log <- safely(log)
safe_log(10)
safe_log("a")
list("a", 10, 100) |>
map(safe_log) |>
transpose()
# This is a bit easier to work with if you supply a default value
# of the same type and use the simplify argument to transpose():
safe_log <- safely(log, otherwise = NA_real_)
list("a", 10, 100) |>
map(safe_log) |>
transpose() |>
simplify_all()
}
\seealso{
Other adverbs:
\code{\link{auto_browse}()},
\code{\link{compose}()},
\code{\link{insistently}()},
\code{\link{negate}()},
\code{\link{partial}()},
\code{\link{possibly}()},
\code{\link{quietly}()},
\code{\link{slowly}()}
}
\concept{adverbs}
purrr/man/map_if.Rd 0000644 0001762 0000144 00000007463 14460311734 013736 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/map-if-at.R
\name{map_if}
\alias{map_if}
\alias{map_at}
\title{Apply a function to each element of a vector conditionally}
\usage{
map_if(.x, .p, .f, ..., .else = NULL)
map_at(.x, .at, .f, ..., .progress = FALSE)
}
\arguments{
\item{.x}{A list or atomic vector.}
\item{.p}{A single predicate function, a formula describing such a
predicate function, or a logical vector of the same length as \code{.x}.
Alternatively, if the elements of \code{.x} are themselves lists of
objects, a string indicating the name of a logical element in the
inner lists. Only those elements where \code{.p} evaluates to
\code{TRUE} will be modified.}
\item{.f}{A function, specified in one of the following ways:
\itemize{
\item A named function, e.g. \code{mean}.
\item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
\item A formula, e.g. \code{~ .x + 1}. You must use \code{.x} to refer to the first
argument. Only recommended if you require backward compatibility with
older versions of R.
\item A string, integer, or list, e.g. \code{"idx"}, \code{1}, or \code{list("idx", 1)} which
are shorthand for \verb{\\(x) pluck(x, "idx")}, \verb{\\(x) pluck(x, 1)}, and
\verb{\\(x) pluck(x, "idx", 1)} respectively. Optionally supply \code{.default} to
set a default value if the indexed element is \code{NULL} or does not exist.
}}
\item{...}{Additional arguments passed on to the mapped function.
We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
\if{html}{\out{
}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{
}}
This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}
\item{.else}{A function applied to elements of \code{.x} for which \code{.p}
returns \code{FALSE}.}
\item{.at}{A logical, integer, or character vector giving the elements
to select. Alternatively, a function that takes a vector of names,
and returns a logical, integer, or character vector of elements to select.
\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}: if the tidyselect package is
installed, you can use \code{vars()} and tidyselect helpers to select
elements.}
\item{.progress}{Whether to show a progress bar. Use \code{TRUE} to turn on
a basic progress bar, use a string to give it a name, or see
\link{progress_bars} for more details.}
}
\description{
The functions \code{map_if()} and \code{map_at()} take \code{.x} as input, apply
the function \code{.f} to some of the elements of \code{.x}, and return a
list of the same length as the input.
\itemize{
\item \code{map_if()} takes a predicate function \code{.p} as input to determine
which elements of \code{.x} are transformed with \code{.f}.
\item \code{map_at()} takes a vector of names or positions \code{.at} to specify
which elements of \code{.x} are transformed with \code{.f}.
}
}
\examples{
# Use a predicate function to decide whether to map a function:
iris |> map_if(is.factor, as.character) |> str()
# Specify an alternative with the `.else` argument:
iris |> map_if(is.factor, as.character, .else = as.integer) |> str()
# Use numeric vector of positions select elements to change:
iris |> map_at(c(4, 5), is.numeric) |> str()
# Use vector of names to specify which elements to change:
iris |> map_at("Species", toupper) |> str()
}
\seealso{
Other map variants:
\code{\link{imap}()},
\code{\link{lmap}()},
\code{\link{map2}()},
\code{\link{map_depth}()},
\code{\link{map}()},
\code{\link{modify}()},
\code{\link{pmap}()}
}
\concept{map variants}
purrr/man/reduce.Rd 0000644 0001762 0000144 00000013011 14314671330 013733 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/reduce.R
\name{reduce}
\alias{reduce}
\alias{reduce2}
\title{Reduce a list to a single value by iteratively applying a binary function}
\usage{
reduce(.x, .f, ..., .init, .dir = c("forward", "backward"))
reduce2(.x, .y, .f, ..., .init)
}
\arguments{
\item{.x}{A list or atomic vector.}
\item{.f}{For \code{reduce()}, a 2-argument function. The function will be passed
the accumulated value as the first argument and the "next" value as the
second argument.
For \code{reduce2()}, a 3-argument function. The function will be passed the
accumulated value as the first argument, the next value of \code{.x} as the
second argument, and the next value of \code{.y} as the third argument.
The reduction terminates early if \code{.f} returns a value wrapped in
a \code{\link[=done]{done()}}.}
\item{...}{Additional arguments passed on to the mapped function.
We now generally recommend against using \code{...} to pass additional
(constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
\if{html}{\out{
}}\preformatted{# Instead of
x |> map(f, 1, 2, collapse = ",")
# do:
x |> map(\\(x) f(x, 1, 2, collapse = ","))
}\if{html}{\out{
}}
This makes it easier to understand which arguments belong to which
function and will tend to yield better error messages.}
\item{.init}{If supplied, will be used as the first value to start
the accumulation, rather than using \code{.x[[1]]}. This is useful if
you want to ensure that \code{reduce} returns a correct value when \code{.x}
is empty. If missing, and \code{.x} is empty, will throw an error.}
\item{.dir}{The direction of reduction as a string, one of
\code{"forward"} (the default) or \code{"backward"}. See the section about
direction below.}
\item{.y}{For \code{reduce2()} and \code{accumulate2()}, an additional
argument that is passed to \code{.f}. If \code{init} is not set, \code{.y}
should be 1 element shorter than \code{.x}.}
}
\description{
\code{reduce()} is an operation that combines the elements of a vector
into a single value. The combination is driven by \code{.f}, a binary
function that takes two values and returns a single value: reducing
\code{f} over \code{1:3} computes the value \code{f(f(1, 2), 3)}.
}
\section{Direction}{
When \code{.f} is an associative operation like \code{+} or \code{c()}, the
direction of reduction does not matter. For instance, reducing the
vector \code{1:3} with the binary function \code{+} computes the sum \code{((1 + 2) + 3)} from the left, and the same sum \code{(1 + (2 + 3))} from the
right.
In other cases, the direction has important consequences on the
reduced value. For instance, reducing a vector with \code{list()} from
the left produces a left-leaning nested list (or tree), while
reducing \code{list()} from the right produces a right-leaning list.
}
\section{Life cycle}{
\code{reduce_right()} is soft-deprecated as of purrr 0.3.0. Please use
the \code{.dir} argument of \code{reduce()} instead. Note that the algorithm
has changed. Whereas \code{reduce_right()} computed \code{f(f(3, 2), 1)},
\verb{reduce(.dir = \\"backward\\")} computes \code{f(1, f(2, 3))}. This is the
standard way of reducing from the right.
To update your code with the same reduction as \code{reduce_right()},
simply reverse your vector and use a left reduction:
\if{html}{\out{
}}
\code{reduce2_right()} is soft-deprecated as of purrr 0.3.0 without
replacement. It is not clear what algorithmic properties should a
right reduction have in this case. Please reach out if you know
about a use case for a right reduction with a ternary function.
}
\examples{
# Reducing `+` computes the sum of a vector while reducing `*`
# computes the product:
1:3 |> reduce(`+`)
1:10 |> reduce(`*`)
# By ignoring the input vector (nxt), you can turn output of one step into
# the input for the next. This code takes 10 steps of a random walk:
reduce(1:10, \(acc, nxt) acc + rnorm(1), .init = 0)
# When the operation is associative, the direction of reduction
# does not matter:
reduce(1:4, `+`)
reduce(1:4, `+`, .dir = "backward")
# However with non-associative operations, the reduced value will
# be different as a function of the direction. For instance,
# `list()` will create left-leaning lists when reducing from the
# right, and right-leaning lists otherwise:
str(reduce(1:4, list))
str(reduce(1:4, list, .dir = "backward"))
# reduce2() takes a ternary function and a second vector that is
# one element smaller than the first vector:
paste2 <- function(x, y, sep = ".") paste(x, y, sep = sep)
letters[1:4] |> reduce(paste2)
letters[1:4] |> reduce2(c("-", ".", "-"), paste2)
x <- list(c(0, 1), c(2, 3), c(4, 5))
y <- list(c(6, 7), c(8, 9))
reduce2(x, y, paste)
# You can shortcircuit a reduction and terminate it early by
# returning a value wrapped in a done(). In the following example
# we return early if the result-so-far, which is passed on the LHS,
# meets a condition:
paste3 <- function(out, input, sep = ".") {
if (nchar(out) > 4) {
return(done(out))
}
paste(out, input, sep = sep)
}
letters |> reduce(paste3)
# Here the early return branch checks the incoming inputs passed on
# the RHS:
paste4 <- function(out, input, sep = ".") {
if (input == "j") {
return(done(out))
}
paste(out, input, sep = sep)
}
letters |> reduce(paste4)
}
\seealso{
\code{\link[=accumulate]{accumulate()}} for a version that returns all intermediate
values of the reduction.
}
purrr/man/partial.Rd 0000644 0001762 0000144 00000010327 14304371054 014126 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/adverb-partial.R
\name{partial}
\alias{partial}
\title{Partially apply a function, filling in some arguments}
\usage{
partial(
.f,
...,
.env = deprecated(),
.lazy = deprecated(),
.first = deprecated()
)
}
\arguments{
\item{.f}{a function. For the output source to read well, this should be a
named function.}
\item{...}{named arguments to \code{.f} that should be partially applied.
Pass an empty \verb{... = } argument to specify the position of future
arguments relative to partialised ones. See
\code{\link[rlang:call_modify]{rlang::call_modify()}} to learn more about this syntax.
These dots support quasiquotation. If you unquote a value, it is
evaluated only once at function creation time. Otherwise, it is
evaluated each time the function is called.}
\item{.env}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} The environments are
now captured via quosures.}
\item{.lazy}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please unquote the
arguments that should be evaluated once at function creation time
with \verb{!!}.}
\item{.first}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please pass an
empty argument \verb{... = } to specify the position of future
arguments.}
}
\value{
A function that takes the same arguments as \code{.f}, but returns
a different value, as described above.
}
\description{
Partial function application allows you to modify a function by pre-filling
some of the arguments. It is particularly useful in conjunction with
functionals and other function operators.
}
\details{
\code{partial()} creates a function that takes \code{...} arguments. Unlike
\code{\link[=compose]{compose()}} and other function operators like \code{\link[=negate]{negate()}}, it
doesn't reuse the function signature of \code{.f}. This is because
\code{partial()} explicitly supports NSE functions that use
\code{substitute()} on their arguments. The only way to support those is
to forward arguments through dots.
Other unsupported patterns:
\itemize{
\item It is not possible to call \code{partial()} repeatedly on the same
argument to pre-fill it with a different expression.
\item It is not possible to refer to other arguments in pre-filled
argument.
}
}
\section{Adverbs}{
This function is called an adverb because it modifies the effect of a
function (a verb). If you'd like to include a function created an adverb
in a package, be sure to read \link{faq-adverbs-export}.
}
\examples{
# Partial is designed to replace the use of anonymous functions for
# filling in function arguments. Instead of:
compact1 <- function(x) discard(x, is.null)
# we can write:
compact2 <- partial(discard, .p = is.null)
# partial() works fine with functions that do non-standard
# evaluation
my_long_variable <- 1:10
plot2 <- partial(plot, my_long_variable)
plot2()
plot2(runif(10), type = "l")
# Note that you currently can't partialise arguments multiple times:
my_mean <- partial(mean, na.rm = TRUE)
my_mean <- partial(my_mean, na.rm = FALSE)
try(my_mean(1:10))
# The evaluation of arguments normally occurs "lazily". Concretely,
# this means that arguments are repeatedly evaluated across invocations:
f <- partial(runif, n = rpois(1, 5))
f
f()
f()
# You can unquote an argument to fix it to a particular value.
# Unquoted arguments are evaluated only once when the function is created:
f <- partial(runif, n = !!rpois(1, 5))
f
f()
f()
# By default, partialised arguments are passed before new ones:
my_list <- partial(list, 1, 2)
my_list("foo")
# Control the position of these arguments by passing an empty
# `... = ` argument:
my_list <- partial(list, 1, ... = , 2)
my_list("foo")
}
\seealso{
Other adverbs:
\code{\link{auto_browse}()},
\code{\link{compose}()},
\code{\link{insistently}()},
\code{\link{negate}()},
\code{\link{possibly}()},
\code{\link{quietly}()},
\code{\link{safely}()},
\code{\link{slowly}()}
}
\concept{adverbs}
purrr/man/insistently.Rd 0000644 0001762 0000144 00000005617 14355342401 015065 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/adverb-insistently.R
\name{insistently}
\alias{insistently}
\title{Transform a function to wait then retry after an error}
\usage{
insistently(f, rate = rate_backoff(), quiet = TRUE)
}
\arguments{
\item{f}{A function to modify, specified in one of the following ways:
\itemize{
\item A named function, e.g. \code{mean}.
\item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
\item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
compatibility with older versions of R.
}}
\item{rate}{A \link[=rate-helpers]{rate} object. Defaults to jittered exponential
backoff.}
\item{quiet}{Hide errors (\code{TRUE}, the default), or display them
as they occur?}
}
\value{
A function that takes the same arguments as \code{.f}, but returns
a different value, as described above.
}
\description{
\code{insistently()} takes a function and modifies it to retry after given
amount of time whenever it errors.
}
\section{Adverbs}{
This function is called an adverb because it modifies the effect of a
function (a verb). If you'd like to include a function created an adverb
in a package, be sure to read \link{faq-adverbs-export}.
}
\examples{
# For the purpose of this example, we first create a custom rate
# object with a low waiting time between attempts:
rate <- rate_delay(0.1)
# insistently() makes a function repeatedly try to work
risky_runif <- function(lo = 0, hi = 1) {
y <- runif(1, lo, hi)
if(y < 0.9) {
stop(y, " is too small")
}
y
}
# Let's now create an exponential backoff rate with a low waiting
# time between attempts:
rate <- rate_backoff(pause_base = 0.1, pause_min = 0.005, max_times = 4)
# Modify your function to run insistently.
insistent_risky_runif <- insistently(risky_runif, rate, quiet = FALSE)
set.seed(6) # Succeeding seed
insistent_risky_runif()
set.seed(3) # Failing seed
try(insistent_risky_runif())
# You can also use other types of rate settings, like a delay rate
# that waits for a fixed amount of time. Be aware that a delay rate
# has an infinite amount of attempts by default:
rate <- rate_delay(0.2, max_times = 3)
insistent_risky_runif <- insistently(risky_runif, rate = rate, quiet = FALSE)
try(insistent_risky_runif())
# insistently() and possibly() are a useful combination
rate <- rate_backoff(pause_base = 0.1, pause_min = 0.005)
possibly_insistent_risky_runif <- possibly(insistent_risky_runif, otherwise = -99)
set.seed(6)
possibly_insistent_risky_runif()
set.seed(3)
possibly_insistent_risky_runif()
}
\seealso{
\code{\link[httr:RETRY]{httr::RETRY()}} is a special case of \code{\link[=insistently]{insistently()}} for
HTTP verbs.
Other adverbs:
\code{\link{auto_browse}()},
\code{\link{compose}()},
\code{\link{negate}()},
\code{\link{partial}()},
\code{\link{possibly}()},
\code{\link{quietly}()},
\code{\link{safely}()},
\code{\link{slowly}()}
}
\concept{adverbs}
purrr/man/attr_getter.Rd 0000644 0001762 0000144 00000002124 14304371054 015012 0 ustar ligges users % Generated by roxygen2: do not edit by hand
% Please edit documentation in R/pluck.R
\name{attr_getter}
\alias{attr_getter}
\title{Create an attribute getter function}
\usage{
attr_getter(attr)
}
\arguments{
\item{attr}{An attribute name as string.}
}
\description{
\code{attr_getter()} generates an attribute accessor function; i.e., it
generates a function for extracting an attribute with a given
name. Unlike the base R \code{attr()} function with default options, it
doesn't use partial matching.
}
\examples{
# attr_getter() takes an attribute name and returns a function to
# access the attribute:
get_rownames <- attr_getter("row.names")
get_rownames(mtcars)
# These getter functions are handy in conjunction with pluck() for
# extracting deeply into a data structure. Here we'll first
# extract by position, then by attribute:
obj1 <- structure("obj", obj_attr = "foo")
obj2 <- structure("obj", obj_attr = "bar")
x <- list(obj1, obj2)
pluck(x, 1, attr_getter("obj_attr")) # From first object
pluck(x, 2, attr_getter("obj_attr")) # From second object
}
\seealso{
\code{\link[=pluck]{pluck()}}
}
purrr/man/figures/ 0000755 0001762 0000144 00000000000 14304371054 013644 5 ustar ligges users purrr/man/figures/lifecycle-defunct.svg 0000644 0001762 0000144 00000001704 14304371054 017754 0 ustar ligges users