.
9 |
10 | Brief description of the problem
11 |
12 | ```r
13 | # insert reprex here
14 | ```
15 |
--------------------------------------------------------------------------------
/.github/move.yml:
--------------------------------------------------------------------------------
1 | # Configuration for move-issues bot - https://github.com/dessant/move-issues
2 |
3 | # Delete the command comment when it contains no other content
4 | deleteCommand: true
5 |
6 | # Close the source issue after moving
7 | closeSourceIssue: true
8 |
9 | # Lock the source issue after moving
10 | lockSourceIssue: false
11 |
12 | # Mention issue and comment authors
13 | mentionAuthors: true
14 |
15 | # Preserve mentions in the issue content
16 | keepContentMentions: true
17 |
18 | # Set custom aliases for targets
19 | # aliases:
20 | # r: repo
21 | # or: owner/repo
22 |
--------------------------------------------------------------------------------
/.github/workflows/R-CMD-check.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | #
4 | # NOTE: This workflow is overkill for most R packages and
5 | # check-standard.yaml is likely a better choice.
6 | # usethis::use_github_action("check-standard") will install it.
7 | on:
8 | push:
9 | branches: [main, master]
10 | pull_request:
11 | branches: [main, master]
12 |
13 | name: R-CMD-check.yaml
14 |
15 | permissions: read-all
16 |
17 | jobs:
18 | R-CMD-check:
19 | runs-on: ${{ matrix.config.os }}
20 |
21 | name: ${{ matrix.config.os }} (${{ matrix.config.r }})
22 |
23 | strategy:
24 | fail-fast: false
25 | matrix:
26 | config:
27 | - {os: macos-latest, r: 'release'}
28 |
29 | - {os: windows-latest, r: 'release'}
30 | # use 4.0 or 4.1 to check with rtools40's older compiler
31 | - {os: windows-latest, r: 'oldrel-4'}
32 |
33 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
34 | - {os: ubuntu-latest, r: 'release'}
35 | - {os: ubuntu-latest, r: 'oldrel-1'}
36 | - {os: ubuntu-latest, r: 'oldrel-2'}
37 | - {os: ubuntu-latest, r: 'oldrel-3'}
38 | - {os: ubuntu-latest, r: 'oldrel-4'}
39 |
40 | env:
41 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
42 | R_KEEP_PKG_SOURCE: yes
43 |
44 | steps:
45 | - uses: actions/checkout@v4
46 |
47 | - uses: r-lib/actions/setup-pandoc@v2
48 |
49 | - uses: r-lib/actions/setup-r@v2
50 | with:
51 | r-version: ${{ matrix.config.r }}
52 | http-user-agent: ${{ matrix.config.http-user-agent }}
53 | use-public-rspm: true
54 |
55 | - uses: r-lib/actions/setup-r-dependencies@v2
56 | with:
57 | extra-packages: any::rcmdcheck
58 | needs: check
59 |
60 | - uses: r-lib/actions/check-r-package@v2
61 | with:
62 | upload-snapshots: true
63 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
64 |
--------------------------------------------------------------------------------
/.github/workflows/pkgdown.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 | release:
9 | types: [published]
10 | workflow_dispatch:
11 |
12 | name: pkgdown.yaml
13 |
14 | permissions: read-all
15 |
16 | jobs:
17 | pkgdown:
18 | runs-on: ubuntu-latest
19 | # Only restrict concurrency for non-PR jobs
20 | concurrency:
21 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
22 | env:
23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
24 | permissions:
25 | contents: write
26 | steps:
27 | - uses: actions/checkout@v4
28 |
29 | - uses: r-lib/actions/setup-pandoc@v2
30 |
31 | - uses: r-lib/actions/setup-r@v2
32 | with:
33 | use-public-rspm: true
34 |
35 | - uses: r-lib/actions/setup-r-dependencies@v2
36 | with:
37 | extra-packages: any::pkgdown, local::.
38 | needs: website
39 |
40 | - name: Build site
41 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
42 | shell: Rscript {0}
43 |
44 | - name: Deploy to GitHub pages 🚀
45 | if: github.event_name != 'pull_request'
46 | uses: JamesIves/github-pages-deploy-action@v4.5.0
47 | with:
48 | clean: false
49 | branch: gh-pages
50 | folder: docs
51 |
--------------------------------------------------------------------------------
/.github/workflows/test-coverage.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 |
9 | name: test-coverage.yaml
10 |
11 | permissions: read-all
12 |
13 | jobs:
14 | test-coverage:
15 | runs-on: ubuntu-latest
16 | env:
17 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 |
22 | - uses: r-lib/actions/setup-r@v2
23 | with:
24 | use-public-rspm: true
25 |
26 | - uses: r-lib/actions/setup-r-dependencies@v2
27 | with:
28 | extra-packages: any::covr, any::xml2
29 | needs: coverage
30 |
31 | - name: Test coverage
32 | run: |
33 | cov <- covr::package_coverage(
34 | quiet = FALSE,
35 | clean = FALSE,
36 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
37 | )
38 | covr::to_cobertura(cov)
39 | shell: Rscript {0}
40 |
41 | - uses: codecov/codecov-action@v4
42 | with:
43 | fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }}
44 | file: ./cobertura.xml
45 | plugin: noop
46 | disable_search: true
47 | token: ${{ secrets.CODECOV_TOKEN }}
48 |
49 | - name: Show testthat output
50 | if: always()
51 | run: |
52 | ## --------------------------------------------------------------------
53 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
54 | shell: bash
55 |
56 | - name: Upload test results
57 | if: failure()
58 | uses: actions/upload-artifact@v4
59 | with:
60 | name: coverage-test-failures
61 | path: ${{ runner.temp }}/package
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .Rproj.user
2 | .Rhistory
3 | .RData
4 | inst/doc
5 | revdep/checks
6 | revdep/library
7 | TAGS
8 | .httr-oauth
9 | docs
10 | compile_commands.json
11 | .cache
12 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: purrr
2 | Title: Functional Programming Tools
3 | Version: 1.0.4.9000
4 | Authors@R: c(
5 | person("Hadley", "Wickham", , "hadley@posit.co", role = c("aut", "cre"),
6 | comment = c(ORCID = "0000-0003-4757-117X")),
7 | person("Lionel", "Henry", , "lionel@posit.co", role = "aut"),
8 | person("Posit Software, PBC", role = c("cph", "fnd"),
9 | comment = c(ROR = "https://ror.org/03wc8by49"))
10 | )
11 | Description: A complete and consistent functional programming toolkit for
12 | R.
13 | License: MIT + file LICENSE
14 | URL: https://purrr.tidyverse.org/, https://github.com/tidyverse/purrr
15 | BugReports: https://github.com/tidyverse/purrr/issues
16 | Depends:
17 | R (>= 4.0)
18 | Imports:
19 | cli (>= 3.6.1),
20 | lifecycle (>= 1.0.3),
21 | magrittr (>= 1.5.0),
22 | rlang (>= 1.1.1),
23 | vctrs (>= 0.6.3)
24 | Suggests:
25 | carrier (>= 0.1.1),
26 | covr,
27 | dplyr (>= 0.7.8),
28 | httr,
29 | knitr,
30 | lubridate,
31 | mirai (>= 2.3.0),
32 | rmarkdown,
33 | testthat (>= 3.0.0),
34 | tibble,
35 | tidyselect
36 | LinkingTo:
37 | cli
38 | VignetteBuilder:
39 | knitr
40 | Biarch: true
41 | Config/build/compilation-database: true
42 | Config/Needs/website: tidyverse/tidytemplate, tidyr
43 | Config/testthat/edition: 3
44 | Config/testthat/parallel: TRUE
45 | Encoding: UTF-8
46 | Roxygen: list(markdown = TRUE)
47 | RoxygenNote: 7.3.2
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2023
2 | COPYRIGHT HOLDER: purrr authors
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2023 purrr authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/R/adverb-auto-browse.R:
--------------------------------------------------------------------------------
1 | #' Wrap a function so it will automatically `browse()` on error
2 | #'
3 | #' A function wrapped with `auto_browse()` will automatically enter an
4 | #' interactive debugger using [browser()] when ever it encounters an error.
5 | #'
6 | #' @inheritParams safely
7 | #' @inheritSection safely Adverbs
8 | #' @inherit safely return
9 | #' @family adverbs
10 | #' @export
11 | #' @examples
12 | #' # For interactive usage, auto_browse() is useful because it automatically
13 | #' # starts a browser() in the right place.
14 | #' f <- function(x) {
15 | #' y <- 20
16 | #' if (x > 5) {
17 | #' stop("!")
18 | #' } else {
19 | #' x
20 | #' }
21 | #' }
22 | #' if (interactive()) {
23 | #' map(1:6, auto_browse(f))
24 | #' }
25 | #'
26 | auto_browse <- function(.f) {
27 | if (is_primitive(.f)) {
28 | cli::cli_abort(
29 | "{.arg .f} must not be a primitive function.",
30 | arg = ".f"
31 | )
32 | }
33 |
34 | function(...) {
35 | withCallingHandlers(
36 | .f(...),
37 | error = function(e) {
38 | # 1: h(simpleError(msg, call))
39 | # 2: .handleSimpleError(function (e) <...>
40 | # 3: stop(...)
41 | frame <- sys.frame(4)
42 | browse_in_frame(frame)
43 | },
44 | warning = function(e) {
45 | if (getOption("warn") >= 2) {
46 | frame <- sys.frame(7)
47 | browse_in_frame(frame)
48 | }
49 | }
50 | )
51 | }
52 | }
53 |
54 | browse_in_frame <- function(frame) {
55 | # ESS should problably set `.Platform$GUI == "ESS"`
56 | # In the meantime, check that ESSR is attached
57 | if (is_attached("ESSR")) {
58 | # Workaround ESS issue
59 | with_env(frame, on.exit({
60 | browser()
61 | NULL
62 | }))
63 | return_from(frame)
64 | } else {
65 | eval_bare(quote(browser()), env = frame)
66 | }
67 | }
68 |
69 |
--------------------------------------------------------------------------------
/R/adverb-negate.R:
--------------------------------------------------------------------------------
1 | #' Negate a predicate function so it selects what it previously rejected
2 | #'
3 | #' Negating a function changes `TRUE` to `FALSE` and `FALSE` to `TRUE`.
4 | #'
5 | #' @inheritParams keep
6 | #' @inheritSection safely Adverbs
7 | #' @family adverbs
8 | #' @return A new predicate function.
9 | #' @export
10 | #' @examples
11 | #' x <- list(x = 1:10, y = rbernoulli(10), z = letters)
12 | #' x |> keep(is.numeric) |> names()
13 | #' x |> keep(negate(is.numeric)) |> names()
14 | #' # Same as
15 | #' x |> discard(is.numeric)
16 | negate <- function(.p) {
17 | compose(`!`, as_mapper(.p))
18 | }
19 |
--------------------------------------------------------------------------------
/R/adverb-possibly.R:
--------------------------------------------------------------------------------
1 | #' Wrap a function to return a value instead of an error
2 | #'
3 | #' Create a modified version of `.f` that return a default value (`otherwise`)
4 | #' whenever an error occurs.
5 | #'
6 | #' @inheritParams safely
7 | #' @inheritSection safely Adverbs
8 | #' @inherit safely return
9 | #' @family adverbs
10 | #' @export
11 | #' @examples
12 | #' # To replace errors with a default value, use possibly().
13 | #' list("a", 10, 100) |>
14 | #' map_dbl(possibly(log, NA_real_))
15 | #'
16 | #' # The default, NULL, will be discarded with `list_c()`
17 | #' list("a", 10, 100) |>
18 | #' map(possibly(log)) |>
19 | #' list_c()
20 | possibly <- function(.f, otherwise = NULL, quiet = TRUE) {
21 | .f <- as_mapper(.f)
22 | force(otherwise)
23 | check_bool(quiet)
24 |
25 | function(...) {
26 | tryCatch(.f(...),
27 | error = function(e) {
28 | if (!quiet)
29 | message("Error: ", conditionMessage(e))
30 | otherwise
31 | }
32 | )
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/R/adverb-quietly.R:
--------------------------------------------------------------------------------
1 | #' Wrap a function to capture side-effects
2 | #'
3 | #' Create a modified version of `.f` that captures side-effects along with
4 | #' the return value of the function and returns a list containing
5 | #' the `result`, `output`, `messages` and `warnings`.
6 | #'
7 | #' @inheritParams safely
8 | #' @inheritSection safely Adverbs
9 | #' @inherit safely return
10 | #' @family adverbs
11 | #' @export
12 | #' @examples
13 | #' f <- function() {
14 | #' print("Hi!")
15 | #' message("Hello")
16 | #' warning("How are ya?")
17 | #' "Gidday"
18 | #' }
19 | #' f()
20 | #'
21 | #' f_quiet <- quietly(f)
22 | #' str(f_quiet())
23 | quietly <- function(.f) {
24 | .f <- as_mapper(.f)
25 | function(...) capture_output(.f(...))
26 | }
27 |
28 | capture_output <- function(code) {
29 | warnings <- character()
30 | wHandler <- function(w) {
31 | warnings <<- c(warnings, conditionMessage(w))
32 | invokeRestart("muffleWarning")
33 | }
34 |
35 | messages <- character()
36 | mHandler <- function(m) {
37 | messages <<- c(messages, conditionMessage(m))
38 | invokeRestart("muffleMessage")
39 | }
40 |
41 | temp <- file()
42 | sink(temp)
43 | on.exit({
44 | sink()
45 | close(temp)
46 | })
47 |
48 | result <- withCallingHandlers(
49 | code,
50 | warning = wHandler,
51 | message = mHandler
52 | )
53 |
54 | output <- paste0(readLines(temp, warn = FALSE), collapse = "\n")
55 |
56 | list(
57 | result = result,
58 | output = output,
59 | warnings = warnings,
60 | messages = messages
61 | )
62 | }
63 |
--------------------------------------------------------------------------------
/R/adverb-safely.R:
--------------------------------------------------------------------------------
1 | #' Wrap a function to capture errors
2 | #'
3 | #' Creates a modified version of `.f` that always succeeds. It returns a list
4 | #' with components `result` and `error`. If the function succeeds, `result`
5 | #' contains the returned value and `error` is `NULL`. If an error occurred,
6 | #' `error` is an `error` object and `result` is either `NULL` or `otherwise`.
7 | #'
8 | #' # Adverbs
9 | #' This function is called an adverb because it modifies the effect of a
10 | #' function (a verb). If you'd like to include a function created an adverb
11 | #' in a package, be sure to read [faq-adverbs-export].
12 | #'
13 | #' @param .f A function to modify, specified in one of the following ways:
14 | #' * A named function, e.g. `mean`.
15 | #' * An anonymous function, e.g. `\(x) x + 1` or `function(x) x + 1`.
16 | #' * A formula, e.g. `~ .x + 1`. Only recommended if you require backward
17 | #' compatibility with older versions of R.
18 | #' @param otherwise Default value to use when an error occurs.
19 | #' @param quiet Hide errors (`TRUE`, the default), or display them
20 | #' as they occur?
21 | #' @returns A function that takes the same arguments as `.f`, but returns
22 | #' a different value, as described above.
23 | #' @family adverbs
24 | #' @export
25 | #' @examples
26 | #' safe_log <- safely(log)
27 | #' safe_log(10)
28 | #' safe_log("a")
29 | #'
30 | #' list("a", 10, 100) |>
31 | #' map(safe_log) |>
32 | #' transpose()
33 | #'
34 | #' # This is a bit easier to work with if you supply a default value
35 | #' # of the same type and use the simplify argument to transpose():
36 | #' safe_log <- safely(log, otherwise = NA_real_)
37 | #' list("a", 10, 100) |>
38 | #' map(safe_log) |>
39 | #' transpose() |>
40 | #' simplify_all()
41 | safely <- function(.f, otherwise = NULL, quiet = TRUE) {
42 | .f <- as_mapper(.f)
43 | force(otherwise)
44 | check_bool(quiet)
45 |
46 | function(...) capture_error(.f(...), otherwise, quiet)
47 | }
48 |
49 | capture_error <- function(code, otherwise = NULL, quiet = TRUE) {
50 | tryCatch(
51 | list(result = code, error = NULL),
52 | error = function(e) {
53 | if (!quiet)
54 | message("Error: ", conditionMessage(e))
55 |
56 | list(result = otherwise, error = e)
57 | }
58 | )
59 | }
60 |
--------------------------------------------------------------------------------
/R/adverb-slowly.R:
--------------------------------------------------------------------------------
1 | #' Wrap a function to wait between executions
2 | #'
3 | #' `slowly()` takes a function and modifies it to wait a given
4 | #' amount of time between each call.
5 | #'
6 | #' @inheritParams insistently
7 | #' @param rate A [rate][rate-helpers] object. Defaults to a constant delay.
8 | #' @inheritSection safely Adverbs
9 | #' @inherit safely return
10 | #' @family adverbs
11 | #' @export
12 | #' @examples
13 | #' # For these example, we first create a custom rate
14 | #' # with a low waiting time between attempts:
15 | #' rate <- rate_delay(0.1)
16 | #'
17 | #' # slowly() causes a function to sleep for a given time between calls:
18 | #' slow_runif <- slowly(\(x) runif(1), rate = rate, quiet = FALSE)
19 | #' out <- map(1:5, slow_runif)
20 | slowly <- function(f, rate = rate_delay(), quiet = TRUE) {
21 | f <- as_mapper(f)
22 | check_rate(rate)
23 | check_bool(quiet)
24 |
25 | function(...) {
26 | rate_sleep(rate, quiet = quiet)
27 | f(...)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/R/cleancall.R:
--------------------------------------------------------------------------------
1 | call_with_cleanup <- function(ptr, ...) {
2 | .Call(cleancall_call, pairlist(ptr, ...), parent.frame())
3 | }
4 |
--------------------------------------------------------------------------------
/R/coerce.R:
--------------------------------------------------------------------------------
1 | # Used internally by map and flatten.
2 | # Exposed here for testing
3 | coerce <- function(x, type) {
4 | .Call(coerce_impl, x, type)
5 | }
6 |
7 | coerce_lgl <- function(x) coerce(x, "logical")
8 | coerce_int <- function(x) coerce(x, "integer")
9 | coerce_dbl <- function(x) coerce(x, "double")
10 | coerce_chr <- function(x) {
11 | local_deprecation_user_env()
12 | coerce(x, "character")
13 | }
14 |
15 |
16 | deprecate_to_char <- function(type) {
17 | lifecycle::deprecate_warn(
18 | "1.0.0",
19 | I(paste0("Automatic coercion from ", type, " to character")),
20 | I("an explicit call to `as.character()` within `map_chr()`"),
21 | always = TRUE,
22 | user_env = the$deprecation_user_env
23 | )
24 | }
25 |
26 |
27 | # Can rewrite after https://github.com/r-lib/rlang/issues/1643
28 | local_deprecation_user_env <- function(user_env = caller_env(2), frame = caller_env()) {
29 |
30 | old <- the$deprecation_user_env
31 | the$deprecation_user_env <- user_env
32 | defer(the$deprecation_user_env <- old, frame)
33 | }
34 |
35 | # Lightweight equivalent of withr::defer()
36 | defer <- function(expr, env = caller_env(), after = FALSE) {
37 | thunk <- as.call(list(function() expr))
38 | do.call(on.exit, list(thunk, TRUE, after), envir = env)
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/R/deprec-along.R:
--------------------------------------------------------------------------------
1 | #' Create a list of given length
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("deprecated")`
5 | #'
6 | #' This function was deprecated in purrr 1.0.0 since it's not related to the
7 | #' core purpose of purrr.
8 | #'
9 | #' It can be useful to create an empty list that you plan to fill later. This is
10 | #' similar to the idea of [seq_along()], which creates a vector of the same
11 | #' length as its input.
12 | #'
13 | #' @param x A vector.
14 | #' @return A list of the same length as `x`.
15 | #' @keywords internal
16 | #' @examples
17 | #' x <- 1:5
18 | #' seq_along(x)
19 | #' list_along(x)
20 | #' @name along
21 | #' @rdname along
22 | #' @export
23 | list_along <- function(x) {
24 | lifecycle::deprecate_soft("1.0.0", "list_along()", I("rep_along(x, list())"))
25 |
26 | vector("list", length(x))
27 | }
28 |
--------------------------------------------------------------------------------
/R/deprec-map.R:
--------------------------------------------------------------------------------
1 | #' Map at depth
2 | #'
3 | #' This function is defunct and has been replaced by [map_depth()].
4 | #' See also [modify_depth()] for a version that preserves the types of
5 | #' the elements of the tree.
6 | #'
7 | #' @export
8 | #' @keywords internal
9 | at_depth <- function(.x, .depth, .f, ...) {
10 | lifecycle::deprecate_stop("0.3.0", "at_depth()", "map_depth()")
11 | }
12 |
--------------------------------------------------------------------------------
/R/deprec-prepend.R:
--------------------------------------------------------------------------------
1 | #' Prepend a vector
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("deprecated")`
5 | #'
6 | #' This function was deprecated in purrr 1.0.0 because it's not related to the
7 | #' core purpose of purrr.
8 | #'
9 | #' This is a companion to [append()] to help merging two
10 | #' lists or atomic vectors. `prepend()` is a clearer semantic
11 | #' signal than `c()` that a vector is to be merged at the beginning of
12 | #' another, especially in a pipe chain.
13 | #'
14 | #' @param x the vector to be modified.
15 | #' @param values to be included in the modified vector.
16 | #' @param before a subscript, before which the values are to be appended. If
17 | #' `NULL`, values will be appended at the beginning even for `x` of length 0.
18 | #' @return A merged vector.
19 | #' @keywords internal
20 | #' @export
21 | #' @examples
22 | #' x <- as.list(1:3)
23 | #'
24 | #' x |> append("a")
25 | #' x |> prepend("a")
26 | #' x |> prepend(list("a", "b"), before = 3)
27 | #' prepend(list(), x)
28 | prepend <- function(x, values, before = NULL) {
29 | lifecycle::deprecate_soft("1.0.0", "prepend()", I("append(after = 0)"))
30 |
31 | n <- length(x)
32 | stopifnot(is.null(before) || (before > 0 && before <= n))
33 |
34 | if (is.null(before) || before == 1) {
35 | c(values, x)
36 | } else {
37 | c(x[1:(before - 1)], values, x[before:n])
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/R/deprec-rerun.R:
--------------------------------------------------------------------------------
1 | #' Re-run expressions multiple times
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("deprecated")`
5 | #'
6 | #' This function was deprecated in purrr 1.0.0 because we believe that NSE
7 | #' functions are not a good fit for purrr. Also, `rerun(n, x)` can just as
8 | #' easily be expressed as `map(1:n, \(i) x)`
9 | #'
10 | #' `rerun()` is a convenient way of generating sample data. It works similarly to
11 | #' \code{\link{replicate}(..., simplify = FALSE)}.
12 | #'
13 | #' @param .n Number of times to run expressions
14 | #' @param ... Expressions to re-run.
15 | #' @return A list of length `.n`. Each element of `...` will be
16 | #' re-run once for each `.n`.
17 | #'
18 | #' There is one special case: if there's a single unnamed input, the second
19 | #' level list will be dropped. In this case, `rerun(n, x)` behaves like
20 | #' `replicate(n, x, simplify = FALSE)`.
21 | #' @export
22 | #' @keywords internal
23 | #' @examples
24 | #' # old
25 | #' 5 |> rerun(rnorm(5)) |> str()
26 | #' # new
27 | #' 1:5 |> map(\(i) rnorm(5)) |> str()
28 | #'
29 | #' # old
30 | #' 5 |>
31 | #' rerun(x = rnorm(5), y = rnorm(5)) |>
32 | #' map_dbl(\(l) cor(l$x, l$y))
33 | #' # new
34 | #' 1:5 |>
35 | #' map(\(i) list(x = rnorm(5), y = rnorm(5))) |>
36 | #' map_dbl(\(l) cor(l$x, l$y))
37 | rerun <- function(.n, ...) {
38 | deprec_rerun(.n, ..., .purrr_user_env = caller_env())
39 |
40 | dots <- quos(...)
41 |
42 | # Special case: if single unnamed argument, insert directly into the output
43 | # rather than wrapping in a list.
44 | if (length(dots) == 1 && !is_named(dots)) {
45 | dots <- dots[[1]]
46 | eval_dots <- eval_tidy
47 | } else {
48 | eval_dots <- function(x) lapply(x, eval_tidy)
49 | }
50 |
51 | out <- vector("list", .n)
52 | for (i in seq_len(.n)) {
53 | out[[i]] <- eval_dots(dots)
54 | }
55 | out
56 | }
57 |
58 | deprec_rerun <- function(.n, ..., .purrr_user_env) {
59 | n <- .n
60 | old <- substitute(rerun(n, ...))
61 | if (dots_n(...) == 1) {
62 | new <- substitute(map(1:n, ~ ...))
63 | } else {
64 | new <- substitute(map(1:n, ~ list(...)))
65 | }
66 |
67 | lifecycle::deprecate_soft(
68 | when = "1.0.0",
69 | what = "rerun()",
70 | with = "map()",
71 | details = c(
72 | " " = "# Previously",
73 | " " = expr_deparse(old),
74 | "",
75 | " " = "# Now",
76 | " " = expr_deparse(new)
77 | ),
78 | user_env = .purrr_user_env
79 | )
80 | }
81 |
--------------------------------------------------------------------------------
/R/deprec-splice.R:
--------------------------------------------------------------------------------
1 | #' Splice objects and lists of objects into a list
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("deprecated")`
5 | #'
6 | #' This function was deprecated in purrr 1.0.0 because we no longer believe that
7 | #' this style of implicit/automatic splicing is a good idea; instead use
8 | #' `rlang::list2()` + `!!!` or [list_flatten()].
9 | #'
10 | #' `splice()` splices all arguments into a list. Non-list objects and lists
11 | #' with a S3 class are encapsulated in a list before concatenation.
12 | #'
13 | #' @param ... Objects to concatenate.
14 | #' @return A list.
15 | #' @keywords internal
16 | #' @examples
17 | #' inputs <- list(arg1 = "a", arg2 = "b")
18 | #'
19 | #' # splice() concatenates the elements of inputs with arg3
20 | #' splice(inputs, arg3 = c("c1", "c2")) |> str()
21 | #' list(inputs, arg3 = c("c1", "c2")) |> str()
22 | #' c(inputs, arg3 = c("c1", "c2")) |> str()
23 | #' @export
24 | splice <- function(...) {
25 | lifecycle::deprecate_soft("1.0.0", "splice()", "list_flatten()")
26 |
27 | splice_if(list(...), is_bare_list)
28 | }
29 |
30 | splice_if <- function(.x, .p) {
31 | unspliced <- !where_if(.x, .p)
32 | out <- modify_if(.x, unspliced, list)
33 | list_flatten(out, name_spec = "{inner}")
34 | }
35 |
--------------------------------------------------------------------------------
/R/deprec-utils.R:
--------------------------------------------------------------------------------
1 | #' Infix attribute accessor
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("deprecated")`
5 | #'
6 | #' This function was deprecated in purrr 0.3.0. Instead, lease use the `%@%`
7 | #' operator exported in rlang. It has an interface more consistent with `@`:
8 | #' uses NSE, supports S4 fields, and has an assignment variant.
9 | #'
10 | #' @param x Object
11 | #' @param name Attribute name
12 | #' @export
13 | #' @name get-attr
14 | #' @keywords internal
15 | `%@%` <- function(x, name) {
16 | lifecycle::deprecate_warn("0.3.0", I("%@%"), I("rlang::%@%"), always = TRUE)
17 | attr(x, name, exact = TRUE)
18 | }
19 |
20 | #' Generate random sample from a Bernoulli distribution
21 | #'
22 | #' @description
23 | #' `r lifecycle::badge("deprecated")`
24 | #'
25 | #' This function was deprecated in purrr 1.0.0 because it's not related to the
26 | #' core purpose of purrr.
27 | #'
28 | #' @param n Number of samples
29 | #' @param p Probability of getting `TRUE`
30 | #' @return A logical vector
31 | #' @keywords internal
32 | #' @export
33 | #' @examples
34 | #' rbernoulli(10)
35 | #' rbernoulli(100, 0.1)
36 | rbernoulli <- function(n, p = 0.5) {
37 | lifecycle::deprecate_soft("1.0.0", "rbernoulli()")
38 | stats::runif(n) > (1 - p)
39 | }
40 |
41 | #' Generate random sample from a discrete uniform distribution
42 | #'
43 | #' @description
44 | #' `r lifecycle::badge("deprecated")`
45 | #'
46 | #' This function was deprecated in purrr 1.0.0 because it's not related to the
47 | #' core purpose of purrr.
48 | #'
49 | #' @param n Number of samples to draw.
50 | #' @param a,b Range of the distribution (inclusive).
51 | #' @keywords internal
52 | #' @export
53 | #' @examples
54 | #' table(rdunif(1e3, 10))
55 | #' table(rdunif(1e3, 10, -5))
56 | rdunif <- function(n, b, a = 1) {
57 | lifecycle::deprecate_soft("1.0.0", "rdunif()")
58 |
59 | stopifnot(is.numeric(a), length(a) == 1)
60 | stopifnot(is.numeric(b), length(b) == 1)
61 |
62 | a1 <- min(a, b)
63 | b1 <- max(a, b)
64 |
65 | sample(b1 - a1 + 1, n, replace = TRUE) + a1 - 1
66 | }
67 |
--------------------------------------------------------------------------------
/R/every-some-none.R:
--------------------------------------------------------------------------------
1 | #' Do every, some, or none of the elements of a list satisfy a predicate?
2 | #'
3 | #' * `some()` returns `TRUE` when `.p` is `TRUE` for at least one element.
4 | #' * `every()` returns `TRUE` when `.p` is `TRUE` for all elements.
5 | #' * `none()` returns `TRUE` when `.p` is `FALSE` for all elements.
6 | #'
7 | #' @inheritParams keep
8 | #' @param ... Additional arguments passed on to `.p`.
9 | #' @return A logical vector of length 1.
10 | #' @export
11 | #' @examples
12 | #' x <- list(0:10, 5.5)
13 | #' x |> every(is.numeric)
14 | #' x |> every(is.integer)
15 | #' x |> some(is.integer)
16 | #' x |> none(is.character)
17 | #'
18 | #' # Missing values are propagated:
19 | #' some(list(NA, FALSE), identity)
20 | #'
21 | #' # If you need to use these functions in a context where missing values are
22 | #' # unsafe (e.g. in `if ()` conditions), make sure to use safe predicates:
23 | #' if (some(list(NA, FALSE), rlang::is_true)) "foo" else "bar"
24 | every <- function(.x, .p, ...) {
25 | .p <- as_predicate(.p, ..., .mapper = TRUE, .allow_na = TRUE)
26 |
27 | val <- TRUE
28 | for (i in seq_along(.x)) {
29 | val <- val && .p(.x[[i]], ...)
30 |
31 | if (is_false(val)) {
32 | return(FALSE)
33 | }
34 | }
35 |
36 | val
37 | }
38 |
39 | #' @export
40 | #' @rdname every
41 | some <- function(.x, .p, ...) {
42 | .p <- as_predicate(.p, ..., .mapper = TRUE, .allow_na = TRUE)
43 |
44 | val <- FALSE
45 | for (i in seq_along(.x)) {
46 | val <- val || .p(.x[[i]], ...)
47 |
48 | if (is_true(val)) {
49 | return(TRUE)
50 | }
51 | }
52 |
53 | val
54 | }
55 |
56 | #' @export
57 | #' @rdname every
58 | none <- function(.x, .p, ...) {
59 | every(.x, negate(.p), ...)
60 | }
61 |
--------------------------------------------------------------------------------
/R/faq.R:
--------------------------------------------------------------------------------
1 | #' Best practices for exporting adverb-wrapped functions
2 | #'
3 | #' @description
4 | #' Exporting functions created with purrr adverbs in your package
5 | #' requires some precautions because the functions will contain internal
6 | #' purrr code. This means that creating them once and for all when
7 | #' the package is built may cause problems when purrr is updated, because
8 | #' a function that the adverb uses might no longer exist.
9 | #'
10 | #' Instead, either create the modified function once per session on package
11 | #' load or wrap the call within another function every time you use it:
12 | #'
13 | #' * Using the \code{\link[=.onLoad]{.onLoad()}} hook:
14 | #' ```
15 | #' #' My function
16 | #' #' @export
17 | #' insist_my_function <- function(...) "dummy"
18 | #'
19 | #' my_function <- function(...) {
20 | #' # Implementation
21 | #' }
22 | #'
23 | #' .onLoad <- function(lib, pkg) {
24 | #' insist_my_function <<- purrr::insistently(my_function)
25 | #' }
26 | #' ```
27 | #'
28 | #' * Using a wrapper function:
29 | #' ```
30 | #' my_function <- function(...) {
31 | #' # Implementation
32 | #' }
33 | #'
34 | #' #' My function
35 | #' #' @export
36 | #' insist_my_function <- function(...) {
37 | #' purrr::insistently(my_function)(...)
38 | #' }
39 | #' ```
40 | #' @keywords internal
41 | #' @name faq-adverbs-export
42 | NULL
43 |
--------------------------------------------------------------------------------
/R/head-tail.R:
--------------------------------------------------------------------------------
1 | #' Find head/tail that all satisfies a predicate.
2 | #'
3 | #' @inheritParams map_if
4 | #' @inheritParams map
5 | #' @return A vector the same type as `.x`.
6 | #' @export
7 | #' @examples
8 | #' pos <- function(x) x >= 0
9 | #' head_while(5:-5, pos)
10 | #' tail_while(5:-5, negate(pos))
11 | #'
12 | #' big <- function(x) x > 100
13 | #' head_while(0:10, big)
14 | #' tail_while(0:10, big)
15 | head_while <- function(.x, .p, ...) {
16 | # Find location of first FALSE
17 | .p <- as_predicate(.p, ..., .mapper = TRUE)
18 | loc <- detect_index(.x, negate(.p), ...)
19 | if (loc == 0) return(.x)
20 |
21 | .x[seq_len(loc - 1)]
22 | }
23 |
24 | #' @export
25 | #' @rdname head_while
26 | tail_while <- function(.x, .p, ...) {
27 | .p <- as_predicate(.p, ..., .mapper = TRUE)
28 | # Find location of last FALSE
29 | loc <- detect_index(.x, negate(.p), ..., .dir = "backward")
30 | if (loc == 0) return(.x)
31 |
32 | .x[-seq_len(loc)]
33 | }
34 |
--------------------------------------------------------------------------------
/R/imap.R:
--------------------------------------------------------------------------------
1 | #' Apply a function to each element of a vector, and its index
2 | #'
3 | #' `imap(x, ...)`, an indexed map, is short hand for
4 | #' `map2(x, names(x), ...)` if `x` has names, or `map2(x, seq_along(x), ...)`
5 | #' if it does not. This is useful if you need to compute on both the value
6 | #' and the position of an element.
7 | #'
8 | #' @param .f A function, specified in one of the following ways:
9 | #'
10 | #' * A named function, e.g. `paste`.
11 | #' * An anonymous function, e.g. `\(x, idx) x + idx` or
12 | #' `function(x, idx) x + idx`.
13 | #' * A formula, e.g. `~ .x + .y`. You must use `.x` to refer to the
14 | #' current element and `.y` to refer to the current index. Only recommended
15 | #' if you require backward compatibility with older versions of R.
16 | #' @inheritParams map
17 | #' @return A vector the same length as `.x`.
18 | #' @export
19 | #' @family map variants
20 | #' @examples
21 | #' imap_chr(sample(10), paste)
22 | #'
23 | #' imap_chr(sample(10), \(x, idx) paste0(idx, ": ", x))
24 | #'
25 | #' iwalk(mtcars, \(x, idx) cat(idx, ": ", median(x), "\n", sep = ""))
26 | imap <- function(.x, .f, ...) {
27 | .f <- as_mapper(.f, ...)
28 | map2(.x, vec_index(.x), .f, ...)
29 | }
30 |
31 | #' @rdname imap
32 | #' @export
33 | imap_lgl <- function(.x, .f, ...) {
34 | .f <- as_mapper(.f, ...)
35 | map2_lgl(.x, vec_index(.x), .f, ...)
36 | }
37 |
38 | #' @rdname imap
39 | #' @export
40 | imap_chr <- function(.x, .f, ...) {
41 | .f <- as_mapper(.f, ...)
42 | map2_chr(.x, vec_index(.x), .f, ...)
43 | }
44 |
45 | #' @rdname imap
46 | #' @export
47 | imap_int <- function(.x, .f, ...) {
48 | .f <- as_mapper(.f, ...)
49 | map2_int(.x, vec_index(.x), .f, ...)
50 | }
51 |
52 | #' @rdname imap
53 | #' @export
54 | imap_dbl <- function(.x, .f, ...) {
55 | .f <- as_mapper(.f, ...)
56 | map2_dbl(.x, vec_index(.x), .f, ...)
57 | }
58 |
59 | #' @rdname imap
60 | #' @export
61 | imap_vec <- function(.x, .f, ...) {
62 | .f <- as_mapper(.f, ...)
63 | map2_vec(.x, vec_index(.x), .f, ...)
64 | }
65 |
66 |
67 | #' @export
68 | #' @rdname imap
69 | iwalk <- function(.x, .f, ...) {
70 | .f <- as_mapper(.f, ...)
71 | walk2(.x, vec_index(.x), .f, ...)
72 | }
73 |
74 |
75 | vec_index <- function(x) {
76 | names(x) %||% seq_along(x)
77 | }
78 |
--------------------------------------------------------------------------------
/R/map-raw.R:
--------------------------------------------------------------------------------
1 | #' Functions that return raw vectors
2 | #'
3 | #' @description
4 | #' `r lifecycle::badge("deprecated")`
5 | #'
6 | #' These functions were deprecated in purrr 1.0.0 because they are of limited
7 | #' use and you can now use `map_vec()` instead. They are variants of [map()],
8 | #' [map2()], [imap()], [pmap()], and [flatten()] that return raw vectors.
9 | #'
10 | #' @keywords internal
11 | #' @export
12 | map_raw <- function(.x, .f, ...) {
13 | lifecycle::deprecate_soft("1.0.0", "map_raw()", "map_vec()")
14 | map_("raw", .x, .f, ...)
15 | }
16 |
17 | #' @export
18 | #' @rdname map_raw
19 | map2_raw <- function(.x, .y, .f, ...) {
20 | lifecycle::deprecate_soft("1.0.0", "map2_raw()", "map2_vec()")
21 | map2_("raw", .x, .y, .f, ...)
22 | }
23 |
24 | #' @rdname map_raw
25 | #' @export
26 | imap_raw <- function(.x, .f, ...) {
27 | lifecycle::deprecate_soft("1.0.0", "imap_raw()", "imap_vec()")
28 | map2_("raw", .x, vec_index(.x), .f, ...)
29 | }
30 |
31 | #' @export
32 | #' @rdname map_raw
33 | pmap_raw <- function(.l, .f, ...) {
34 | lifecycle::deprecate_soft("1.0.0", "pmap_raw()", "pmap_vec()")
35 | pmap_("raw", .l, .f, ...)
36 | }
37 |
38 | #' @export
39 | #' @rdname map_raw
40 | flatten_raw <- function(.x) {
41 | lifecycle::deprecate_soft("1.0.0", "flatten_raw()")
42 | .Call(vflatten_impl, .x, "raw")
43 | }
44 |
--------------------------------------------------------------------------------
/R/package-purrr.R:
--------------------------------------------------------------------------------
1 | #' @keywords internal
2 | #' @import rlang
3 | #' @import vctrs
4 | #' @importFrom cli cli_progress_bar
5 | #' @importFrom lifecycle deprecated
6 | #' @useDynLib purrr, .registration = TRUE
7 | "_PACKAGE"
8 |
9 | the <- new_environment()
10 |
--------------------------------------------------------------------------------
/R/pluck-depth.R:
--------------------------------------------------------------------------------
1 | #' Compute the depth of a vector
2 | #'
3 | #' The depth of a vector is how many levels that you can index/pluck into it.
4 | #' `pluck_depth()` was previously called `vec_depth()`.
5 | #'
6 | #' @param x A vector
7 | #' @param is_node Optionally override the default criteria for determine an
8 | #' element can be recursed within. The default matches the behaviour of
9 | #' `pluck()` which can recurse into lists and expressions.
10 | #' @return An integer.
11 | #' @export
12 | #' @examples
13 | #' x <- list(
14 | #' list(),
15 | #' list(list()),
16 | #' list(list(list(1)))
17 | #' )
18 | #' pluck_depth(x)
19 | #' x |> map_int(pluck_depth)
20 | pluck_depth <- function(x, is_node = NULL) {
21 | if (is.null(is_node)) {
22 | is_node <- function(x) is.expression(x) || is.list(x)
23 | }
24 | is_node <- as_is_node(is_node)
25 |
26 | if (is_node(x)) {
27 | depths <- map_int(x, pluck_depth, is_node = is_node)
28 | 1L + max(depths, 0L)
29 | } else if (is_atomic(x)) {
30 | 1L
31 | } else {
32 | 0L
33 | }
34 | }
35 |
36 | #' @export
37 | #' @rdname pluck_depth
38 | #' @usage NULL
39 | vec_depth <- function(x) {
40 | lifecycle::deprecate_soft("1.0.0", "vec_depth()", "pluck_depth()")
41 | pluck_depth(x)
42 | }
43 |
--------------------------------------------------------------------------------
/R/reexport-pipe.R:
--------------------------------------------------------------------------------
1 | #' Pipe operator
2 | #'
3 | #' @name %>%
4 | #' @rdname pipe
5 | #' @keywords internal
6 | #' @export
7 | #' @importFrom magrittr %>%
8 | #' @usage lhs \%>\% rhs
9 | NULL
10 |
11 |
--------------------------------------------------------------------------------
/R/reexport-rlang.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | rlang::set_names
3 |
4 | #' @export
5 | rlang::exec
6 |
7 | #' @export
8 | rlang::zap
9 |
10 | #' @export
11 | rlang::`%||%`
12 |
13 | #' @export
14 | rlang::done
15 |
16 | #' @export
17 | rlang::rep_along
18 |
19 | # Predicates ---------------------------------------------------
20 |
21 | #' @export
22 | rlang::is_bare_list
23 |
24 | #' @export
25 | rlang::is_bare_atomic
26 |
27 | #' @export
28 | rlang::is_bare_vector
29 |
30 | #' @export
31 | rlang::is_bare_double
32 |
33 | #' @export
34 | rlang::is_bare_integer
35 |
36 | #' @export
37 | rlang::is_bare_numeric
38 |
39 | #' @export
40 | rlang::is_bare_character
41 |
42 | #' @export
43 | rlang::is_bare_logical
44 |
45 | #' @export
46 | rlang::is_list
47 |
48 | #' @export
49 | rlang::is_atomic
50 |
51 | #' @export
52 | rlang::is_vector
53 |
54 | #' @export
55 | rlang::is_integer
56 |
57 | #' @export
58 | rlang::is_double
59 |
60 | #' @export
61 | rlang::is_character
62 |
63 | #' @export
64 | rlang::is_logical
65 |
66 | #' @export
67 | rlang::is_null
68 |
69 | #' @export
70 | rlang::is_function
71 |
72 | #' @export
73 | rlang::is_scalar_list
74 |
75 | #' @export
76 | rlang::is_scalar_atomic
77 |
78 | #' @export
79 | rlang::is_scalar_vector
80 |
81 | #' @export
82 | rlang::is_scalar_double
83 |
84 | #' @export
85 | rlang::is_scalar_character
86 |
87 | #' @export
88 | rlang::is_scalar_logical
89 |
90 | #' @export
91 | rlang::is_scalar_integer
92 |
93 | #' @export
94 | rlang::is_empty
95 |
96 | #' @export
97 | rlang::is_formula
98 |
--------------------------------------------------------------------------------
/cleanup:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env sh
2 |
3 | rm -f man/macros/examples.Rd
4 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | comment: false
2 |
3 | coverage:
4 | status:
5 | project:
6 | default:
7 | target: auto
8 | threshold: 1%
9 | informational: true
10 | patch:
11 | default:
12 | target: auto
13 | threshold: 1%
14 | informational: true
15 |
--------------------------------------------------------------------------------
/configure:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env sh
2 |
3 | # Check that this is not just ./configure. We need to run this
4 | # from R CMD INSTALL, to have the R env vars set.
5 |
6 | if [ -z "$R_HOME" ]; then
7 | echo >&2 R_HOME is not set, are you running R CMD INSTALL?
8 | exit 1
9 | fi
10 |
11 | # Find the R binary we need to use. This is a bit trickier on
12 | # Windows, because it has two architectures. On windows R_ARCH_BIN
13 | # is set, so this should work everywhere.
14 | RBIN="${R_HOME}/bin${R_ARCH_BIN}/R"
15 |
16 | "$RBIN" --vanilla --slave -f tools/examples.R
17 |
--------------------------------------------------------------------------------
/configure.win:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env sh
2 |
3 | sh ./configure
4 |
--------------------------------------------------------------------------------
/cran-comments.md:
--------------------------------------------------------------------------------
1 | ## R CMD check results
2 |
3 | 0 errors | 0 warnings | 0 notes
4 |
5 | ## revdepcheck results
6 |
7 | This was a patch release to fix R CMD check issues. I saw 2 false positives in my revdepchecks (meta and waywiser) and failed to check a further 45 packages.
8 |
--------------------------------------------------------------------------------
/man/along.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-along.R
3 | \name{along}
4 | \alias{along}
5 | \alias{list_along}
6 | \title{Create a list of given length}
7 | \usage{
8 | list_along(x)
9 | }
10 | \arguments{
11 | \item{x}{A vector.}
12 | }
13 | \value{
14 | A list of the same length as \code{x}.
15 | }
16 | \description{
17 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
18 |
19 | This function was deprecated in purrr 1.0.0 since it's not related to the
20 | core purpose of purrr.
21 |
22 | It can be useful to create an empty list that you plan to fill later. This is
23 | similar to the idea of \code{\link[=seq_along]{seq_along()}}, which creates a vector of the same
24 | length as its input.
25 | }
26 | \examples{
27 | x <- 1:5
28 | seq_along(x)
29 | list_along(x)
30 | }
31 | \keyword{internal}
32 |
--------------------------------------------------------------------------------
/man/array-coercion.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/arrays.R
3 | \name{array-coercion}
4 | \alias{array-coercion}
5 | \alias{array_branch}
6 | \alias{array_tree}
7 | \title{Coerce array to list}
8 | \usage{
9 | array_branch(array, margin = NULL)
10 |
11 | array_tree(array, margin = NULL)
12 | }
13 | \arguments{
14 | \item{array}{An array to coerce into a list.}
15 |
16 | \item{margin}{A numeric vector indicating the positions of the
17 | indices to be to be enlisted. If \code{NULL}, a full margin is
18 | used. If \code{numeric(0)}, the array as a whole is wrapped in a
19 | list.}
20 | }
21 | \description{
22 | \code{array_branch()} and \code{array_tree()} enable arrays to be
23 | used with purrr's functionals by turning them into lists. The
24 | details of the coercion are controlled by the \code{margin}
25 | argument. \code{array_tree()} creates an hierarchical list (a tree)
26 | that has as many levels as dimensions specified in \code{margin},
27 | while \code{array_branch()} creates a flat list (by analogy, a
28 | branch) along all mentioned dimensions.
29 | }
30 | \details{
31 | When no margin is specified, all dimensions are used by
32 | default. When \code{margin} is a numeric vector of length zero, the
33 | whole array is wrapped in a list.
34 | }
35 | \examples{
36 | # We create an array with 3 dimensions
37 | x <- array(1:12, c(2, 2, 3))
38 |
39 | # A full margin for such an array would be the vector 1:3. This is
40 | # the default if you don't specify a margin
41 |
42 | # Creating a branch along the full margin is equivalent to
43 | # as.list(array) and produces a list of size length(x):
44 | array_branch(x) |> str()
45 |
46 | # A branch along the first dimension yields a list of length 2
47 | # with each element containing a 2x3 array:
48 | array_branch(x, 1) |> str()
49 |
50 | # A branch along the first and third dimensions yields a list of
51 | # length 2x3 whose elements contain a vector of length 2:
52 | array_branch(x, c(1, 3)) |> str()
53 |
54 | # Creating a tree from the full margin creates a list of lists of
55 | # lists:
56 | array_tree(x) |> str()
57 |
58 | # The ordering and the depth of the tree are controlled by the
59 | # margin argument:
60 | array_tree(x, c(3, 1)) |> str()
61 | }
62 |
--------------------------------------------------------------------------------
/man/as_vector.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/superseded-simplify.R
3 | \name{as_vector}
4 | \alias{as_vector}
5 | \alias{simplify}
6 | \alias{simplify_all}
7 | \title{Coerce a list to a vector}
8 | \usage{
9 | as_vector(.x, .type = NULL)
10 |
11 | simplify(.x, .type = NULL)
12 |
13 | simplify_all(.x, .type = NULL)
14 | }
15 | \arguments{
16 | \item{.x}{A list of vectors}
17 |
18 | \item{.type}{Can be a vector mold specifying both the type and the
19 | length of the vectors to be concatenated, such as \code{numeric(1)}
20 | or \code{integer(4)}. Alternatively, it can be a string describing
21 | the type, one of: "logical", "integer", "double", "complex",
22 | "character" or "raw".}
23 | }
24 | \description{
25 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
26 |
27 | These functions were superseded in purrr 1.0.0 in favour of
28 | \code{list_simplify()} which has more consistent semantics based on vctrs
29 | principles:
30 | \itemize{
31 | \item \code{as_vector(x)} is now \code{list_simplify(x)}
32 | \item \code{simplify(x)} is now \code{list_simplify(x, strict = FALSE)}
33 | \item \code{simplify_all(x)} is \code{map(x, list_simplify, strict = FALSE)}
34 | }
35 |
36 | Superseded functions will not go away, but will only receive critical
37 | bug fixes.
38 | }
39 | \examples{
40 | # was
41 | as.list(letters) |> as_vector("character")
42 | # now
43 | as.list(letters) |> list_simplify(ptype = character())
44 |
45 | # was:
46 | list(1:2, 3:4, 5:6) |> as_vector(integer(2))
47 | # now:
48 | list(1:2, 3:4, 5:6) |> list_c(ptype = integer())
49 | }
50 | \keyword{internal}
51 |
--------------------------------------------------------------------------------
/man/at_depth.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-map.R
3 | \name{at_depth}
4 | \alias{at_depth}
5 | \title{Map at depth}
6 | \usage{
7 | at_depth(.x, .depth, .f, ...)
8 | }
9 | \description{
10 | This function is defunct and has been replaced by \code{\link[=map_depth]{map_depth()}}.
11 | See also \code{\link[=modify_depth]{modify_depth()}} for a version that preserves the types of
12 | the elements of the tree.
13 | }
14 | \keyword{internal}
15 |
--------------------------------------------------------------------------------
/man/attr_getter.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/pluck.R
3 | \name{attr_getter}
4 | \alias{attr_getter}
5 | \title{Create an attribute getter function}
6 | \usage{
7 | attr_getter(attr)
8 | }
9 | \arguments{
10 | \item{attr}{An attribute name as string.}
11 | }
12 | \description{
13 | \code{attr_getter()} generates an attribute accessor function; i.e., it
14 | generates a function for extracting an attribute with a given
15 | name. Unlike the base R \code{attr()} function with default options, it
16 | doesn't use partial matching.
17 | }
18 | \examples{
19 | # attr_getter() takes an attribute name and returns a function to
20 | # access the attribute:
21 | get_rownames <- attr_getter("row.names")
22 | get_rownames(mtcars)
23 |
24 | # These getter functions are handy in conjunction with pluck() for
25 | # extracting deeply into a data structure. Here we'll first
26 | # extract by position, then by attribute:
27 | obj1 <- structure("obj", obj_attr = "foo")
28 | obj2 <- structure("obj", obj_attr = "bar")
29 | x <- list(obj1, obj2)
30 |
31 | pluck(x, 1, attr_getter("obj_attr")) # From first object
32 | pluck(x, 2, attr_getter("obj_attr")) # From second object
33 | }
34 | \seealso{
35 | \code{\link[=pluck]{pluck()}}
36 | }
37 |
--------------------------------------------------------------------------------
/man/auto_browse.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-auto-browse.R
3 | \name{auto_browse}
4 | \alias{auto_browse}
5 | \title{Wrap a function so it will automatically \code{browse()} on error}
6 | \usage{
7 | auto_browse(.f)
8 | }
9 | \arguments{
10 | \item{.f}{A function to modify, specified in one of the following ways:
11 | \itemize{
12 | \item A named function, e.g. \code{mean}.
13 | \item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
14 | \item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
15 | compatibility with older versions of R.
16 | }}
17 | }
18 | \value{
19 | A function that takes the same arguments as \code{.f}, but returns
20 | a different value, as described above.
21 | }
22 | \description{
23 | A function wrapped with \code{auto_browse()} will automatically enter an
24 | interactive debugger using \code{\link[=browser]{browser()}} when ever it encounters an error.
25 | }
26 | \section{Adverbs}{
27 | This function is called an adverb because it modifies the effect of a
28 | function (a verb). If you'd like to include a function created an adverb
29 | in a package, be sure to read \link{faq-adverbs-export}.
30 | }
31 |
32 | \examples{
33 | # For interactive usage, auto_browse() is useful because it automatically
34 | # starts a browser() in the right place.
35 | f <- function(x) {
36 | y <- 20
37 | if (x > 5) {
38 | stop("!")
39 | } else {
40 | x
41 | }
42 | }
43 | if (interactive()) {
44 | map(1:6, auto_browse(f))
45 | }
46 |
47 | }
48 | \seealso{
49 | Other adverbs:
50 | \code{\link{compose}()},
51 | \code{\link{insistently}()},
52 | \code{\link{negate}()},
53 | \code{\link{partial}()},
54 | \code{\link{possibly}()},
55 | \code{\link{quietly}()},
56 | \code{\link{safely}()},
57 | \code{\link{slowly}()}
58 | }
59 | \concept{adverbs}
60 |
--------------------------------------------------------------------------------
/man/chuck.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/pluck.R
3 | \name{chuck}
4 | \alias{chuck}
5 | \title{Get an element deep within a nested data structure, failing if it doesn't
6 | exist}
7 | \usage{
8 | chuck(.x, ...)
9 | }
10 | \arguments{
11 | \item{.x}{A vector or environment}
12 |
13 | \item{...}{A list of accessors for indexing into the object. Can be
14 | an positive integer, a negative integer (to index from the right),
15 | a string (to index into names), or an accessor function
16 | (except for the assignment variants which only support names and
17 | positions). If the object being indexed is an S4 object,
18 | accessing it by name will return the corresponding slot.
19 |
20 | \link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if
21 | your accessors are stored in a list, you can splice that in with
22 | \verb{!!!}.}
23 | }
24 | \description{
25 | \code{chuck()} implements a generalised form of \code{[[} that allow you to index
26 | deeply and flexibly into data structures. If the index you are trying to
27 | access does not exist (or is \code{NULL}), it will throw (i.e. chuck) an error.
28 | }
29 | \examples{
30 | x <- list(a = 1, b = 2)
31 |
32 | # When indexing an element that doesn't exist `[[` sometimes returns NULL:
33 | x[["y"]]
34 | # and sometimes errors:
35 | try(x[[3]])
36 |
37 | # chuck() consistently errors:
38 | try(chuck(x, "y"))
39 | try(chuck(x, 3))
40 | }
41 | \seealso{
42 | \code{\link[=pluck]{pluck()}} for a quiet equivalent.
43 | }
44 |
--------------------------------------------------------------------------------
/man/compose.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-compose.R
3 | \name{compose}
4 | \alias{compose}
5 | \title{Compose multiple functions together to create a new function}
6 | \usage{
7 | compose(..., .dir = c("backward", "forward"))
8 | }
9 | \arguments{
10 | \item{...}{Functions to apply in order (from right to left by
11 | default). Formulas are converted to functions in the usual way.
12 |
13 | \link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if
14 | your functions are stored in a list, you can splice that in with
15 | \verb{!!!}.}
16 |
17 | \item{.dir}{If \code{"backward"} (the default), the functions are called
18 | in the reverse order, from right to left, as is conventional in
19 | mathematics. If \code{"forward"}, they are called from left to right.}
20 | }
21 | \value{
22 | A function
23 | }
24 | \description{
25 | Create a new function that is the composition of multiple functions,
26 | i.e. \code{compose(f, g)} is equivalent to \code{function(...) f(g(...))}.
27 | }
28 | \section{Adverbs}{
29 | This function is called an adverb because it modifies the effect of a
30 | function (a verb). If you'd like to include a function created an adverb
31 | in a package, be sure to read \link{faq-adverbs-export}.
32 | }
33 |
34 | \examples{
35 | not_null <- compose(`!`, is.null)
36 | not_null(4)
37 | not_null(NULL)
38 |
39 | add1 <- function(x) x + 1
40 | compose(add1, add1)(8)
41 |
42 | fn <- compose(\(x) paste(x, "foo"), \(x) paste(x, "bar"))
43 | fn("input")
44 |
45 | # Lists of functions can be spliced with !!!
46 | fns <- list(
47 | function(x) paste(x, "foo"),
48 | \(x) paste(x, "bar")
49 | )
50 | fn <- compose(!!!fns)
51 | fn("input")
52 | }
53 | \seealso{
54 | Other adverbs:
55 | \code{\link{auto_browse}()},
56 | \code{\link{insistently}()},
57 | \code{\link{negate}()},
58 | \code{\link{partial}()},
59 | \code{\link{possibly}()},
60 | \code{\link{quietly}()},
61 | \code{\link{safely}()},
62 | \code{\link{slowly}()}
63 | }
64 | \concept{adverbs}
65 |
--------------------------------------------------------------------------------
/man/every.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/every-some-none.R
3 | \name{every}
4 | \alias{every}
5 | \alias{some}
6 | \alias{none}
7 | \title{Do every, some, or none of the elements of a list satisfy a predicate?}
8 | \usage{
9 | every(.x, .p, ...)
10 |
11 | some(.x, .p, ...)
12 |
13 | none(.x, .p, ...)
14 | }
15 | \arguments{
16 | \item{.x}{A list or vector.}
17 |
18 | \item{.p}{A predicate function (i.e. a function that returns either \code{TRUE}
19 | or \code{FALSE}) specified in one of the following ways:
20 | \itemize{
21 | \item A named function, e.g. \code{is.character}.
22 | \item An anonymous function, e.g. \verb{\\(x) all(x < 0)} or \code{function(x) all(x < 0)}.
23 | \item A formula, e.g. \code{~ all(.x < 0)}. You must use \code{.x} to refer to the first
24 | argument). Only recommended if you require backward compatibility with
25 | older versions of R.
26 | }}
27 |
28 | \item{...}{Additional arguments passed on to \code{.p}.}
29 | }
30 | \value{
31 | A logical vector of length 1.
32 | }
33 | \description{
34 | \itemize{
35 | \item \code{some()} returns \code{TRUE} when \code{.p} is \code{TRUE} for at least one element.
36 | \item \code{every()} returns \code{TRUE} when \code{.p} is \code{TRUE} for all elements.
37 | \item \code{none()} returns \code{TRUE} when \code{.p} is \code{FALSE} for all elements.
38 | }
39 | }
40 | \examples{
41 | x <- list(0:10, 5.5)
42 | x |> every(is.numeric)
43 | x |> every(is.integer)
44 | x |> some(is.integer)
45 | x |> none(is.character)
46 |
47 | # Missing values are propagated:
48 | some(list(NA, FALSE), identity)
49 |
50 | # If you need to use these functions in a context where missing values are
51 | # unsafe (e.g. in `if ()` conditions), make sure to use safe predicates:
52 | if (some(list(NA, FALSE), rlang::is_true)) "foo" else "bar"
53 | }
54 |
--------------------------------------------------------------------------------
/man/faq-adverbs-export.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/faq.R
3 | \name{faq-adverbs-export}
4 | \alias{faq-adverbs-export}
5 | \title{Best practices for exporting adverb-wrapped functions}
6 | \description{
7 | Exporting functions created with purrr adverbs in your package
8 | requires some precautions because the functions will contain internal
9 | purrr code. This means that creating them once and for all when
10 | the package is built may cause problems when purrr is updated, because
11 | a function that the adverb uses might no longer exist.
12 |
13 | Instead, either create the modified function once per session on package
14 | load or wrap the call within another function every time you use it:
15 | \itemize{
16 | \item Using the \code{\link[=.onLoad]{.onLoad()}} hook:
17 |
18 | \if{html}{\out{}}\preformatted{#' My function
19 | #' @export
20 | insist_my_function <- function(...) "dummy"
21 |
22 | my_function <- function(...) \{
23 | # Implementation
24 | \}
25 |
26 | .onLoad <- function(lib, pkg) \{
27 | insist_my_function <<- purrr::insistently(my_function)
28 | \}
29 | }\if{html}{\out{
}}
30 | \item Using a wrapper function:
31 |
32 | \if{html}{\out{}}\preformatted{my_function <- function(...) \{
33 | # Implementation
34 | \}
35 |
36 | #' My function
37 | #' @export
38 | insist_my_function <- function(...) \{
39 | purrr::insistently(my_function)(...)
40 | \}
41 | }\if{html}{\out{
}}
42 | }
43 | }
44 | \keyword{internal}
45 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-archived.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle archived archived
--------------------------------------------------------------------------------
/man/figures/lifecycle-defunct.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle defunct defunct
--------------------------------------------------------------------------------
/man/figures/lifecycle-deprecated.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle deprecated deprecated
--------------------------------------------------------------------------------
/man/figures/lifecycle-experimental.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle experimental experimental
--------------------------------------------------------------------------------
/man/figures/lifecycle-maturing.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle maturing maturing
--------------------------------------------------------------------------------
/man/figures/lifecycle-questioning.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle questioning questioning
--------------------------------------------------------------------------------
/man/figures/lifecycle-soft-deprecated.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle soft-deprecated soft-deprecated
--------------------------------------------------------------------------------
/man/figures/lifecycle-stable.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle stable stable
--------------------------------------------------------------------------------
/man/figures/lifecycle-superseded.svg:
--------------------------------------------------------------------------------
1 | lifecycle lifecycle superseded superseded
--------------------------------------------------------------------------------
/man/figures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/man/figures/logo.png
--------------------------------------------------------------------------------
/man/flatten.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/superseded-flatten.R
3 | \name{flatten}
4 | \alias{flatten}
5 | \alias{flatten_lgl}
6 | \alias{flatten_int}
7 | \alias{flatten_dbl}
8 | \alias{flatten_chr}
9 | \alias{flatten_dfr}
10 | \alias{flatten_dfc}
11 | \alias{flatten_df}
12 | \title{Flatten a list of lists into a simple vector}
13 | \usage{
14 | flatten(.x)
15 |
16 | flatten_lgl(.x)
17 |
18 | flatten_int(.x)
19 |
20 | flatten_dbl(.x)
21 |
22 | flatten_chr(.x)
23 |
24 | flatten_dfr(.x, .id = NULL)
25 |
26 | flatten_dfc(.x)
27 | }
28 | \arguments{
29 | \item{.x}{A list to flatten. The contents of the list can be anything for
30 | \code{flatten()} (as a list is returned), but the contents must match the
31 | type for the other functions.}
32 | }
33 | \value{
34 | \code{flatten()} returns a list, \code{flatten_lgl()} a logical
35 | vector, \code{flatten_int()} an integer vector, \code{flatten_dbl()} a
36 | double vector, and \code{flatten_chr()} a character vector.
37 |
38 | \code{flatten_dfr()} and \code{flatten_dfc()} return data frames created by
39 | row-binding and column-binding respectively. They require dplyr to
40 | be installed.
41 | }
42 | \description{
43 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
44 |
45 | These functions were superseded in purrr 1.0.0 because their behaviour was
46 | inconsistent. Superseded functions will not go away, but will only receive
47 | critical bug fixes.
48 | \itemize{
49 | \item \code{flatten()} has been superseded by \code{\link[=list_flatten]{list_flatten()}}.
50 | \item \code{flatten_lgl()}, \code{flatten_int()}, \code{flatten_dbl()}, and \code{flatten_chr()}
51 | have been superseded by \code{\link[=list_c]{list_c()}}.
52 | \item \code{flatten_dfr()} and \code{flatten_dfc()} have been superseded by \code{\link[=list_rbind]{list_rbind()}}
53 | and \code{\link[=list_cbind]{list_cbind()}} respectively.
54 | }
55 | }
56 | \examples{
57 | x <- map(1:3, \(i) sample(4))
58 | x
59 |
60 | # was
61 | x |> flatten_int() |> str()
62 | # now
63 | x |> list_c() |> str()
64 |
65 | x <- list(list(1, 2), list(3, 4))
66 | # was
67 | x |> flatten() |> str()
68 | # now
69 | x |> list_flatten() |> str()
70 | }
71 | \keyword{internal}
72 |
--------------------------------------------------------------------------------
/man/get-attr.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-utils.R
3 | \name{get-attr}
4 | \alias{get-attr}
5 | \alias{\%@\%}
6 | \title{Infix attribute accessor}
7 | \usage{
8 | x \%@\% name
9 | }
10 | \arguments{
11 | \item{x}{Object}
12 |
13 | \item{name}{Attribute name}
14 | }
15 | \description{
16 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
17 |
18 | This function was deprecated in purrr 0.3.0. Instead, lease use the \verb{\%@\%}
19 | operator exported in rlang. It has an interface more consistent with \code{@}:
20 | uses NSE, supports S4 fields, and has an assignment variant.
21 | }
22 | \keyword{internal}
23 |
--------------------------------------------------------------------------------
/man/has_element.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/detect.R
3 | \name{has_element}
4 | \alias{has_element}
5 | \title{Does a list contain an object?}
6 | \usage{
7 | has_element(.x, .y)
8 | }
9 | \arguments{
10 | \item{.x}{A list or atomic vector.}
11 |
12 | \item{.y}{Object to test for}
13 | }
14 | \description{
15 | Does a list contain an object?
16 | }
17 | \examples{
18 | x <- list(1:10, 5, 9.9)
19 | x |> has_element(1:10)
20 | x |> has_element(3)
21 | }
22 |
--------------------------------------------------------------------------------
/man/head_while.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/head-tail.R
3 | \name{head_while}
4 | \alias{head_while}
5 | \alias{tail_while}
6 | \title{Find head/tail that all satisfies a predicate.}
7 | \usage{
8 | head_while(.x, .p, ...)
9 |
10 | tail_while(.x, .p, ...)
11 | }
12 | \arguments{
13 | \item{.x}{A list or atomic vector.}
14 |
15 | \item{.p}{A single predicate function, a formula describing such a
16 | predicate function, or a logical vector of the same length as \code{.x}.
17 | Alternatively, if the elements of \code{.x} are themselves lists of
18 | objects, a string indicating the name of a logical element in the
19 | inner lists. Only those elements where \code{.p} evaluates to
20 | \code{TRUE} will be modified.}
21 |
22 | \item{...}{Additional arguments passed on to the mapped function.
23 |
24 | We now generally recommend against using \code{...} to pass additional
25 | (constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
26 |
27 | \if{html}{\out{}}\preformatted{# Instead of
28 | x |> map(f, 1, 2, collapse = ",")
29 | # do:
30 | x |> map(\\(x) f(x, 1, 2, collapse = ","))
31 | }\if{html}{\out{
}}
32 |
33 | This makes it easier to understand which arguments belong to which
34 | function and will tend to yield better error messages.}
35 | }
36 | \value{
37 | A vector the same type as \code{.x}.
38 | }
39 | \description{
40 | Find head/tail that all satisfies a predicate.
41 | }
42 | \examples{
43 | pos <- function(x) x >= 0
44 | head_while(5:-5, pos)
45 | tail_while(5:-5, negate(pos))
46 |
47 | big <- function(x) x > 100
48 | head_while(0:10, big)
49 | tail_while(0:10, big)
50 | }
51 |
--------------------------------------------------------------------------------
/man/imap.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/imap.R
3 | \name{imap}
4 | \alias{imap}
5 | \alias{imap_lgl}
6 | \alias{imap_chr}
7 | \alias{imap_int}
8 | \alias{imap_dbl}
9 | \alias{imap_vec}
10 | \alias{iwalk}
11 | \title{Apply a function to each element of a vector, and its index}
12 | \usage{
13 | imap(.x, .f, ...)
14 |
15 | imap_lgl(.x, .f, ...)
16 |
17 | imap_chr(.x, .f, ...)
18 |
19 | imap_int(.x, .f, ...)
20 |
21 | imap_dbl(.x, .f, ...)
22 |
23 | imap_vec(.x, .f, ...)
24 |
25 | iwalk(.x, .f, ...)
26 | }
27 | \arguments{
28 | \item{.x}{A list or atomic vector.}
29 |
30 | \item{.f}{A function, specified in one of the following ways:
31 | \itemize{
32 | \item A named function, e.g. \code{paste}.
33 | \item An anonymous function, e.g. \verb{\\(x, idx) x + idx} or
34 | \code{function(x, idx) x + idx}.
35 | \item A formula, e.g. \code{~ .x + .y}. You must use \code{.x} to refer to the
36 | current element and \code{.y} to refer to the current index. Only recommended
37 | if you require backward compatibility with older versions of R.
38 | }}
39 |
40 | \item{...}{Additional arguments passed on to the mapped function.
41 |
42 | We now generally recommend against using \code{...} to pass additional
43 | (constant) arguments to \code{.f}. Instead use a shorthand anonymous function:
44 |
45 | \if{html}{\out{}}\preformatted{# Instead of
46 | x |> map(f, 1, 2, collapse = ",")
47 | # do:
48 | x |> map(\\(x) f(x, 1, 2, collapse = ","))
49 | }\if{html}{\out{
}}
50 |
51 | This makes it easier to understand which arguments belong to which
52 | function and will tend to yield better error messages.}
53 | }
54 | \value{
55 | A vector the same length as \code{.x}.
56 | }
57 | \description{
58 | \code{imap(x, ...)}, an indexed map, is short hand for
59 | \code{map2(x, names(x), ...)} if \code{x} has names, or \code{map2(x, seq_along(x), ...)}
60 | if it does not. This is useful if you need to compute on both the value
61 | and the position of an element.
62 | }
63 | \examples{
64 | imap_chr(sample(10), paste)
65 |
66 | imap_chr(sample(10), \(x, idx) paste0(idx, ": ", x))
67 |
68 | iwalk(mtcars, \(x, idx) cat(idx, ": ", median(x), "\n", sep = ""))
69 | }
70 | \seealso{
71 | Other map variants:
72 | \code{\link{lmap}()},
73 | \code{\link{map}()},
74 | \code{\link{map2}()},
75 | \code{\link{map_depth}()},
76 | \code{\link{map_if}()},
77 | \code{\link{modify}()},
78 | \code{\link{pmap}()}
79 | }
80 | \concept{map variants}
81 |
--------------------------------------------------------------------------------
/man/keep.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/keep.R
3 | \name{keep}
4 | \alias{keep}
5 | \alias{discard}
6 | \alias{compact}
7 | \title{Keep/discard elements based on their values}
8 | \usage{
9 | keep(.x, .p, ...)
10 |
11 | discard(.x, .p, ...)
12 |
13 | compact(.x, .p = identity)
14 | }
15 | \arguments{
16 | \item{.x}{A list or vector.}
17 |
18 | \item{.p}{A predicate function (i.e. a function that returns either \code{TRUE}
19 | or \code{FALSE}) specified in one of the following ways:
20 | \itemize{
21 | \item A named function, e.g. \code{is.character}.
22 | \item An anonymous function, e.g. \verb{\\(x) all(x < 0)} or \code{function(x) all(x < 0)}.
23 | \item A formula, e.g. \code{~ all(.x < 0)}. You must use \code{.x} to refer to the first
24 | argument). Only recommended if you require backward compatibility with
25 | older versions of R.
26 | }}
27 |
28 | \item{...}{Additional arguments passed on to \code{.p}.}
29 | }
30 | \description{
31 | \code{keep()} selects all elements where \code{.p} evaluates to \code{TRUE};
32 | \code{discard()} selects all elements where \code{.p} evaluates to \code{FALSE}.
33 | \code{compact()} discards elements where \code{.p} evaluates to an empty vector.
34 | }
35 | \details{
36 | In other languages, \code{keep()} and \code{discard()} are often called \code{select()}/
37 | \code{filter()} and \code{reject()}/ \code{drop()}, but those names are already taken
38 | in R. \code{keep()} is similar to \code{\link[=Filter]{Filter()}}, but the argument order is more
39 | convenient, and the evaluation of the predicate function \code{.p} is stricter.
40 | }
41 | \examples{
42 | rep(10, 10) |>
43 | map(sample, 5) |>
44 | keep(function(x) mean(x) > 6)
45 |
46 | # Or use a formula
47 | rep(10, 10) |>
48 | map(sample, 5) |>
49 | keep(\(x) mean(x) > 6)
50 |
51 | # Using a string instead of a function will select all list elements
52 | # where that subelement is TRUE
53 | x <- rerun(5, a = rbernoulli(1), b = sample(10))
54 | x
55 | x |> keep("a")
56 | x |> discard("a")
57 |
58 | # compact() discards elements that are NULL or that have length zero
59 | list(a = "a", b = NULL, c = integer(0), d = NA, e = list()) |>
60 | compact()
61 | }
62 | \seealso{
63 | \code{\link[=keep_at]{keep_at()}}/\code{\link[=discard_at]{discard_at()}} to keep/discard elements by name.
64 | }
65 |
--------------------------------------------------------------------------------
/man/keep_at.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/keep.R
3 | \name{keep_at}
4 | \alias{keep_at}
5 | \alias{discard_at}
6 | \title{Keep/discard elements based on their name/position}
7 | \usage{
8 | keep_at(x, at)
9 |
10 | discard_at(x, at)
11 | }
12 | \arguments{
13 | \item{x}{A list or atomic vector.}
14 |
15 | \item{at}{A logical, integer, or character vector giving the elements
16 | to select. Alternatively, a function that takes a vector of names,
17 | and returns a logical, integer, or character vector of elements to select.
18 |
19 | \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
20 | installed, you can use \code{vars()} and tidyselect helpers to select
21 | elements.}
22 | }
23 | \description{
24 | Keep/discard elements based on their name/position
25 | }
26 | \examples{
27 | x <- c(a = 1, b = 2, cat = 10, dog = 15, elephant = 5, e = 10)
28 | x |> keep_at(letters)
29 | x |> discard_at(letters)
30 |
31 | # Can also use a function
32 | x |> keep_at(~ nchar(.x) == 3)
33 | x |> discard_at(~ nchar(.x) == 3)
34 | }
35 | \seealso{
36 | \code{\link[=keep]{keep()}}/\code{\link[=discard]{discard()}} to keep/discard elements by value.
37 | }
38 |
--------------------------------------------------------------------------------
/man/list_assign.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/list-modify.R
3 | \name{list_assign}
4 | \alias{list_assign}
5 | \alias{list_modify}
6 | \alias{list_merge}
7 | \title{Modify a list}
8 | \usage{
9 | list_assign(.x, ..., .is_node = NULL)
10 |
11 | list_modify(.x, ..., .is_node = NULL)
12 |
13 | list_merge(.x, ..., .is_node = NULL)
14 | }
15 | \arguments{
16 | \item{.x}{List to modify.}
17 |
18 | \item{...}{New values of a list. Use \code{zap()} to remove values.
19 |
20 | These values should be either all named or all unnamed. When
21 | inputs are all named, they are matched to \code{.x} by name. When they
22 | are all unnamed, they are matched by position.
23 |
24 | \link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if your
25 | replacement values are stored in a list, you can splice that in with
26 | \verb{!!!}.}
27 |
28 | \item{.is_node}{A predicate function that determines whether an element is
29 | a node (by returning \code{TRUE}) or a leaf (by returning \code{FALSE}). The
30 | default value, \code{NULL}, treats simple lists as nodes and everything else
31 | (including richer objects like data frames and linear models) as leaves,
32 | using \code{\link[vctrs:obj_is_list]{vctrs::obj_is_list()}}. To recurse into all objects built on lists
33 | use \code{\link[=is.list]{is.list()}}.}
34 | }
35 | \description{
36 | \itemize{
37 | \item \code{list_assign()} modifies the elements of a list by name or position.
38 | \item \code{list_modify()} modifies the elements of a list recursively.
39 | \item \code{list_merge()} merges the elements of a list recursively.
40 | }
41 |
42 | \code{list_modify()} is inspired by \code{\link[utils:modifyList]{utils::modifyList()}}.
43 | }
44 | \examples{
45 | x <- list(x = 1:10, y = 4, z = list(a = 1, b = 2))
46 | str(x)
47 |
48 | # Update values
49 | str(list_assign(x, a = 1))
50 |
51 | # Replace values
52 | str(list_assign(x, z = 5))
53 | str(list_assign(x, z = NULL))
54 | str(list_assign(x, z = list(a = 1:5)))
55 |
56 | # Replace recursively with list_modify(), leaving the other elements of z alone
57 | str(list_modify(x, z = list(a = 1:5)))
58 |
59 | # Remove values
60 | str(list_assign(x, z = zap()))
61 |
62 | # Combine values with list_merge()
63 | str(list_merge(x, x = 11, z = list(a = 2:5, c = 3)))
64 |
65 | # All these functions support dynamic dots features. Use !!! to splice
66 | # a list of arguments:
67 | l <- list(new = 1, y = zap(), z = 5)
68 | str(list_assign(x, !!!l))
69 | }
70 |
--------------------------------------------------------------------------------
/man/list_c.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/list-combine.R
3 | \name{list_c}
4 | \alias{list_c}
5 | \alias{list_cbind}
6 | \alias{list_rbind}
7 | \title{Combine list elements into a single data structure}
8 | \usage{
9 | list_c(x, ..., ptype = NULL)
10 |
11 | list_cbind(
12 | x,
13 | ...,
14 | name_repair = c("unique", "universal", "check_unique"),
15 | size = NULL
16 | )
17 |
18 | list_rbind(x, ..., names_to = rlang::zap(), ptype = NULL)
19 | }
20 | \arguments{
21 | \item{x}{A list. For \code{list_rbind()} and \code{list_cbind()} the list must
22 | only contain only data frames or \code{NULL}.}
23 |
24 | \item{...}{These dots are for future extensions and must be empty.}
25 |
26 | \item{ptype}{An optional prototype to ensure that the output type is always
27 | the same.}
28 |
29 | \item{name_repair}{One of \code{"unique"}, \code{"universal"}, or \code{"check_unique"}.
30 | See \code{\link[vctrs:vec_as_names]{vctrs::vec_as_names()}} for the meaning of these options.}
31 |
32 | \item{size}{An optional integer size to ensure that every input has the
33 | same size (i.e. number of rows).}
34 |
35 | \item{names_to}{By default, \code{names(x)} are lost. To keep them, supply a
36 | string to \code{names_to} and the names will be saved into a column with that
37 | name. If \code{names_to} is supplied and \code{x} is not named, the position of
38 | the elements will be used instead of the names.}
39 | }
40 | \description{
41 | \itemize{
42 | \item \code{list_c()} combines elements into a vector by concatenating them together
43 | with \code{\link[vctrs:vec_c]{vctrs::vec_c()}}.
44 | \item \code{list_rbind()} combines elements into a data frame by row-binding them
45 | together with \code{\link[vctrs:vec_bind]{vctrs::vec_rbind()}}.
46 | \item \code{list_cbind()} combines elements into a data frame by column-binding them
47 | together with \code{\link[vctrs:vec_bind]{vctrs::vec_cbind()}}.
48 | }
49 | }
50 | \examples{
51 | x1 <- list(a = 1, b = 2, c = 3)
52 | list_c(x1)
53 |
54 | x2 <- list(
55 | a = data.frame(x = 1:2),
56 | b = data.frame(y = "a")
57 | )
58 | list_rbind(x2)
59 | list_rbind(x2, names_to = "id")
60 | list_rbind(unname(x2), names_to = "id")
61 |
62 | list_cbind(x2)
63 | }
64 |
--------------------------------------------------------------------------------
/man/list_flatten.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/list-flatten.R
3 | \name{list_flatten}
4 | \alias{list_flatten}
5 | \title{Flatten a list}
6 | \usage{
7 | list_flatten(
8 | x,
9 | ...,
10 | name_spec = "{outer}_{inner}",
11 | name_repair = c("minimal", "unique", "check_unique", "universal")
12 | )
13 | }
14 | \arguments{
15 | \item{x}{A list.}
16 |
17 | \item{...}{These dots are for future extensions and must be empty.}
18 |
19 | \item{name_spec}{If both inner and outer names are present, control
20 | how they are combined. Should be a glue specification that uses
21 | variables \code{inner} and \code{outer}.}
22 |
23 | \item{name_repair}{One of \code{"minimal"}, \code{"unique"}, \code{"universal"}, or
24 | \code{"check_unique"}. See \code{\link[vctrs:vec_as_names]{vctrs::vec_as_names()}} for the meaning of these
25 | options.}
26 | }
27 | \value{
28 | A list of the same type as \code{x}. The list might be shorter
29 | if \code{x} contains empty lists, the same length if it contains lists
30 | of length 1 or no sub-lists, or longer if it contains lists of
31 | length > 1.
32 | }
33 | \description{
34 | Flattening a list removes a single layer of internal hierarchy,
35 | i.e. it inlines elements that are lists leaving non-lists alone.
36 | }
37 | \examples{
38 | x <- list(1, list(2, 3), list(4, list(5)))
39 | x |> list_flatten() |> str()
40 | x |> list_flatten() |> list_flatten() |> str()
41 |
42 | # Flat lists are left as is
43 | list(1, 2, 3, 4, 5) |> list_flatten() |> str()
44 |
45 | # Empty lists will disappear
46 | list(1, list(), 2, list(3)) |> list_flatten() |> str()
47 |
48 | # Another way to see this is that it reduces the depth of the list
49 | x <- list(
50 | list(),
51 | list(list())
52 | )
53 | x |> pluck_depth()
54 | x |> list_flatten() |> pluck_depth()
55 |
56 | # Use name_spec to control how inner and outer names are combined
57 | x <- list(x = list(a = 1, b = 2), y = list(c = 1, d = 2))
58 | x |> list_flatten() |> names()
59 | x |> list_flatten(name_spec = "{outer}") |> names()
60 | x |> list_flatten(name_spec = "{inner}") |> names()
61 | }
62 |
--------------------------------------------------------------------------------
/man/list_simplify.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/list-simplify.R
3 | \name{list_simplify}
4 | \alias{list_simplify}
5 | \title{Simplify a list to an atomic or S3 vector}
6 | \usage{
7 | list_simplify(x, ..., strict = TRUE, ptype = NULL)
8 | }
9 | \arguments{
10 | \item{x}{A list.}
11 |
12 | \item{...}{These dots are for future extensions and must be empty.}
13 |
14 | \item{strict}{What should happen if simplification fails? If \code{TRUE}
15 | (the default) it will error. If \code{FALSE} and \code{ptype} is not supplied,
16 | it will return \code{x} unchanged.}
17 |
18 | \item{ptype}{An optional prototype to ensure that the output type is always
19 | the same.}
20 | }
21 | \value{
22 | A vector the same length as \code{x}.
23 | }
24 | \description{
25 | Simplification maintains a one-to-one correspondence between the input
26 | and output, implying that each element of \code{x} must contain a one element
27 | vector or a one-row data frame. If you don't want to maintain this
28 | correspondence, then you probably want either \code{\link[=list_c]{list_c()}}/\code{\link[=list_rbind]{list_rbind()}} or
29 | \code{\link[=list_flatten]{list_flatten()}}.
30 | }
31 | \examples{
32 | list_simplify(list(1, 2, 3))
33 |
34 | # Only works when vectors are length one and have compatible types:
35 | try(list_simplify(list(1, 2, 1:3)))
36 | try(list_simplify(list(1, 2, "x")))
37 |
38 | # Unless you strict = FALSE, in which case you get the input back:
39 | list_simplify(list(1, 2, 1:3), strict = FALSE)
40 | list_simplify(list(1, 2, "x"), strict = FALSE)
41 | }
42 |
--------------------------------------------------------------------------------
/man/macros/.gitignore:
--------------------------------------------------------------------------------
1 | examples.Rd
2 |
--------------------------------------------------------------------------------
/man/map_raw.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/map-raw.R
3 | \name{map_raw}
4 | \alias{map_raw}
5 | \alias{map2_raw}
6 | \alias{imap_raw}
7 | \alias{pmap_raw}
8 | \alias{flatten_raw}
9 | \title{Functions that return raw vectors}
10 | \usage{
11 | map_raw(.x, .f, ...)
12 |
13 | map2_raw(.x, .y, .f, ...)
14 |
15 | imap_raw(.x, .f, ...)
16 |
17 | pmap_raw(.l, .f, ...)
18 |
19 | flatten_raw(.x)
20 | }
21 | \description{
22 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
23 |
24 | These functions were deprecated in purrr 1.0.0 because they are of limited
25 | use and you can now use \code{map_vec()} instead. They are variants of \code{\link[=map]{map()}},
26 | \code{\link[=map2]{map2()}}, \code{\link[=imap]{imap()}}, \code{\link[=pmap]{pmap()}}, and \code{\link[=flatten]{flatten()}} that return raw vectors.
27 | }
28 | \keyword{internal}
29 |
--------------------------------------------------------------------------------
/man/modify_in.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/pluck-assign.R
3 | \name{modify_in}
4 | \alias{modify_in}
5 | \alias{assign_in}
6 | \title{Modify a pluck location}
7 | \usage{
8 | modify_in(.x, .where, .f, ...)
9 |
10 | assign_in(x, where, value)
11 | }
12 | \arguments{
13 | \item{.x, x}{A vector or environment}
14 |
15 | \item{.where, where}{A pluck location, as a numeric vector of
16 | positions, a character vector of names, or a list combining both.
17 | The location must exist in the data structure.}
18 |
19 | \item{.f}{A function to apply at the pluck location given by \code{.where}.}
20 |
21 | \item{...}{Arguments passed to \code{.f}.}
22 |
23 | \item{value}{A value to replace in \code{.x} at the pluck location.
24 | Use \code{zap()} to instead remove the element.}
25 | }
26 | \description{
27 | \itemize{
28 | \item \code{assign_in()} takes a data structure and a \link{pluck} location,
29 | assigns a value there, and returns the modified data structure.
30 | \item \code{modify_in()} applies a function to a pluck location, assigns the
31 | result back to that location with \code{\link[=assign_in]{assign_in()}}, and returns the
32 | modified data structure.
33 | }
34 | }
35 | \examples{
36 | # Recall that pluck() returns a component of a data structure that
37 | # might be arbitrarily deep
38 | x <- list(list(bar = 1, foo = 2))
39 | pluck(x, 1, "foo")
40 |
41 | # Use assign_in() to modify the pluck location:
42 | str(assign_in(x, list(1, "foo"), 100))
43 | # Or zap to remove it
44 | str(assign_in(x, list(1, "foo"), zap()))
45 |
46 | # Like pluck(), this works even when the element (or its parents) don't exist
47 | pluck(x, 1, "baz")
48 | str(assign_in(x, list(2, "baz"), 100))
49 |
50 | # modify_in() applies a function to that location and update the
51 | # element in place:
52 | modify_in(x, list(1, "foo"), \(x) x * 200)
53 |
54 | # Additional arguments are passed to the function in the ordinary way:
55 | modify_in(x, list(1, "foo"), `+`, 100)
56 | }
57 | \seealso{
58 | \code{\link[=pluck]{pluck()}}
59 | }
60 |
--------------------------------------------------------------------------------
/man/modify_tree.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/modify-tree.R
3 | \name{modify_tree}
4 | \alias{modify_tree}
5 | \title{Recursively modify a list}
6 | \usage{
7 | modify_tree(
8 | x,
9 | ...,
10 | leaf = identity,
11 | is_node = NULL,
12 | pre = identity,
13 | post = identity
14 | )
15 | }
16 | \arguments{
17 | \item{x}{A list.}
18 |
19 | \item{...}{Reserved for future use. Must be empty}
20 |
21 | \item{leaf}{A function applied to each leaf.}
22 |
23 | \item{is_node}{A predicate function that determines whether an element is
24 | a node (by returning \code{TRUE}) or a leaf (by returning \code{FALSE}). The
25 | default value, \code{NULL}, treats simple lists as nodes and everything else
26 | (including richer objects like data frames and linear models) as leaves,
27 | using \code{\link[vctrs:obj_is_list]{vctrs::obj_is_list()}}. To recurse into all objects built on lists
28 | use \code{\link[=is.list]{is.list()}}.}
29 |
30 | \item{pre, post}{Functions applied to each node. \code{pre} is applied on the
31 | way "down", i.e. before the leaves are transformed with \code{leaf}, while
32 | \code{post} is applied on the way "up", i.e. after the leaves are transformed.}
33 | }
34 | \description{
35 | \code{modify_tree()} allows you to recursively modify a list, supplying functions
36 | that either modify each leaf or each node (or both).
37 | }
38 | \examples{
39 | x <- list(list(a = 2:1, c = list(b1 = 2), b = list(c2 = 3, c1 = 4)))
40 | x |> str()
41 |
42 | # Transform each leaf
43 | x |> modify_tree(leaf = \(x) x + 100) |> str()
44 |
45 | # Recursively sort the nodes
46 | sort_named <- function(x) {
47 | nms <- names(x)
48 | if (!is.null(nms)) {
49 | x[order(nms)]
50 | } else {
51 | x
52 | }
53 | }
54 | x |> modify_tree(post = sort_named) |> str()
55 | }
56 | \seealso{
57 | Other modify variants:
58 | \code{\link{map_depth}()},
59 | \code{\link{modify}()}
60 | }
61 | \concept{modify variants}
62 |
--------------------------------------------------------------------------------
/man/negate.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-negate.R
3 | \name{negate}
4 | \alias{negate}
5 | \title{Negate a predicate function so it selects what it previously rejected}
6 | \usage{
7 | negate(.p)
8 | }
9 | \arguments{
10 | \item{.p}{A predicate function (i.e. a function that returns either \code{TRUE}
11 | or \code{FALSE}) specified in one of the following ways:
12 | \itemize{
13 | \item A named function, e.g. \code{is.character}.
14 | \item An anonymous function, e.g. \verb{\\(x) all(x < 0)} or \code{function(x) all(x < 0)}.
15 | \item A formula, e.g. \code{~ all(.x < 0)}. You must use \code{.x} to refer to the first
16 | argument). Only recommended if you require backward compatibility with
17 | older versions of R.
18 | }}
19 | }
20 | \value{
21 | A new predicate function.
22 | }
23 | \description{
24 | Negating a function changes \code{TRUE} to \code{FALSE} and \code{FALSE} to \code{TRUE}.
25 | }
26 | \section{Adverbs}{
27 | This function is called an adverb because it modifies the effect of a
28 | function (a verb). If you'd like to include a function created an adverb
29 | in a package, be sure to read \link{faq-adverbs-export}.
30 | }
31 |
32 | \examples{
33 | x <- list(x = 1:10, y = rbernoulli(10), z = letters)
34 | x |> keep(is.numeric) |> names()
35 | x |> keep(negate(is.numeric)) |> names()
36 | # Same as
37 | x |> discard(is.numeric)
38 | }
39 | \seealso{
40 | Other adverbs:
41 | \code{\link{auto_browse}()},
42 | \code{\link{compose}()},
43 | \code{\link{insistently}()},
44 | \code{\link{partial}()},
45 | \code{\link{possibly}()},
46 | \code{\link{quietly}()},
47 | \code{\link{safely}()},
48 | \code{\link{slowly}()}
49 | }
50 | \concept{adverbs}
51 |
--------------------------------------------------------------------------------
/man/pipe.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/reexport-pipe.R
3 | \name{\%>\%}
4 | \alias{\%>\%}
5 | \title{Pipe operator}
6 | \usage{
7 | lhs \%>\% rhs
8 | }
9 | \description{
10 | Pipe operator
11 | }
12 | \keyword{internal}
13 |
--------------------------------------------------------------------------------
/man/pluck_depth.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/pluck-depth.R
3 | \name{pluck_depth}
4 | \alias{pluck_depth}
5 | \alias{vec_depth}
6 | \title{Compute the depth of a vector}
7 | \usage{
8 | pluck_depth(x, is_node = NULL)
9 | }
10 | \arguments{
11 | \item{x}{A vector}
12 |
13 | \item{is_node}{Optionally override the default criteria for determine an
14 | element can be recursed within. The default matches the behaviour of
15 | \code{pluck()} which can recurse into lists and expressions.}
16 | }
17 | \value{
18 | An integer.
19 | }
20 | \description{
21 | The depth of a vector is how many levels that you can index/pluck into it.
22 | \code{pluck_depth()} was previously called \code{vec_depth()}.
23 | }
24 | \examples{
25 | x <- list(
26 | list(),
27 | list(list()),
28 | list(list(list(1)))
29 | )
30 | pluck_depth(x)
31 | x |> map_int(pluck_depth)
32 | }
33 |
--------------------------------------------------------------------------------
/man/possibly.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-possibly.R
3 | \name{possibly}
4 | \alias{possibly}
5 | \title{Wrap a function to return a value instead of an error}
6 | \usage{
7 | possibly(.f, otherwise = NULL, quiet = TRUE)
8 | }
9 | \arguments{
10 | \item{.f}{A function to modify, specified in one of the following ways:
11 | \itemize{
12 | \item A named function, e.g. \code{mean}.
13 | \item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
14 | \item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
15 | compatibility with older versions of R.
16 | }}
17 |
18 | \item{otherwise}{Default value to use when an error occurs.}
19 |
20 | \item{quiet}{Hide errors (\code{TRUE}, the default), or display them
21 | as they occur?}
22 | }
23 | \value{
24 | A function that takes the same arguments as \code{.f}, but returns
25 | a different value, as described above.
26 | }
27 | \description{
28 | Create a modified version of \code{.f} that return a default value (\code{otherwise})
29 | whenever an error occurs.
30 | }
31 | \section{Adverbs}{
32 | This function is called an adverb because it modifies the effect of a
33 | function (a verb). If you'd like to include a function created an adverb
34 | in a package, be sure to read \link{faq-adverbs-export}.
35 | }
36 |
37 | \examples{
38 | # To replace errors with a default value, use possibly().
39 | list("a", 10, 100) |>
40 | map_dbl(possibly(log, NA_real_))
41 |
42 | # The default, NULL, will be discarded with `list_c()`
43 | list("a", 10, 100) |>
44 | map(possibly(log)) |>
45 | list_c()
46 | }
47 | \seealso{
48 | Other adverbs:
49 | \code{\link{auto_browse}()},
50 | \code{\link{compose}()},
51 | \code{\link{insistently}()},
52 | \code{\link{negate}()},
53 | \code{\link{partial}()},
54 | \code{\link{quietly}()},
55 | \code{\link{safely}()},
56 | \code{\link{slowly}()}
57 | }
58 | \concept{adverbs}
59 |
--------------------------------------------------------------------------------
/man/prepend.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-prepend.R
3 | \name{prepend}
4 | \alias{prepend}
5 | \title{Prepend a vector}
6 | \usage{
7 | prepend(x, values, before = NULL)
8 | }
9 | \arguments{
10 | \item{x}{the vector to be modified.}
11 |
12 | \item{values}{to be included in the modified vector.}
13 |
14 | \item{before}{a subscript, before which the values are to be appended. If
15 | \code{NULL}, values will be appended at the beginning even for \code{x} of length 0.}
16 | }
17 | \value{
18 | A merged vector.
19 | }
20 | \description{
21 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
22 |
23 | This function was deprecated in purrr 1.0.0 because it's not related to the
24 | core purpose of purrr.
25 |
26 | This is a companion to \code{\link[=append]{append()}} to help merging two
27 | lists or atomic vectors. \code{prepend()} is a clearer semantic
28 | signal than \code{c()} that a vector is to be merged at the beginning of
29 | another, especially in a pipe chain.
30 | }
31 | \examples{
32 | x <- as.list(1:3)
33 |
34 | x |> append("a")
35 | x |> prepend("a")
36 | x |> prepend(list("a", "b"), before = 3)
37 | prepend(list(), x)
38 | }
39 | \keyword{internal}
40 |
--------------------------------------------------------------------------------
/man/purrr-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/package-purrr.R
3 | \docType{package}
4 | \name{purrr-package}
5 | \alias{purrr}
6 | \alias{purrr-package}
7 | \title{purrr: Functional Programming Tools}
8 | \description{
9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}
10 |
11 | A complete and consistent functional programming toolkit for R.
12 | }
13 | \seealso{
14 | Useful links:
15 | \itemize{
16 | \item \url{https://purrr.tidyverse.org/}
17 | \item \url{https://github.com/tidyverse/purrr}
18 | \item Report bugs at \url{https://github.com/tidyverse/purrr/issues}
19 | }
20 |
21 | }
22 | \author{
23 | \strong{Maintainer}: Hadley Wickham \email{hadley@posit.co} (\href{https://orcid.org/0000-0003-4757-117X}{ORCID})
24 |
25 | Authors:
26 | \itemize{
27 | \item Lionel Henry \email{lionel@posit.co}
28 | }
29 |
30 | Other contributors:
31 | \itemize{
32 | \item Posit Software, PBC (https://ror.org/03wc8by49) [copyright holder, funder]
33 | }
34 |
35 | }
36 | \keyword{internal}
37 |
--------------------------------------------------------------------------------
/man/quietly.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-quietly.R
3 | \name{quietly}
4 | \alias{quietly}
5 | \title{Wrap a function to capture side-effects}
6 | \usage{
7 | quietly(.f)
8 | }
9 | \arguments{
10 | \item{.f}{A function to modify, specified in one of the following ways:
11 | \itemize{
12 | \item A named function, e.g. \code{mean}.
13 | \item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
14 | \item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
15 | compatibility with older versions of R.
16 | }}
17 | }
18 | \value{
19 | A function that takes the same arguments as \code{.f}, but returns
20 | a different value, as described above.
21 | }
22 | \description{
23 | Create a modified version of \code{.f} that captures side-effects along with
24 | the return value of the function and returns a list containing
25 | the \code{result}, \code{output}, \code{messages} and \code{warnings}.
26 | }
27 | \section{Adverbs}{
28 | This function is called an adverb because it modifies the effect of a
29 | function (a verb). If you'd like to include a function created an adverb
30 | in a package, be sure to read \link{faq-adverbs-export}.
31 | }
32 |
33 | \examples{
34 | f <- function() {
35 | print("Hi!")
36 | message("Hello")
37 | warning("How are ya?")
38 | "Gidday"
39 | }
40 | f()
41 |
42 | f_quiet <- quietly(f)
43 | str(f_quiet())
44 | }
45 | \seealso{
46 | Other adverbs:
47 | \code{\link{auto_browse}()},
48 | \code{\link{compose}()},
49 | \code{\link{insistently}()},
50 | \code{\link{negate}()},
51 | \code{\link{partial}()},
52 | \code{\link{possibly}()},
53 | \code{\link{safely}()},
54 | \code{\link{slowly}()}
55 | }
56 | \concept{adverbs}
57 |
--------------------------------------------------------------------------------
/man/rate-helpers.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/rate.R
3 | \name{rate-helpers}
4 | \alias{rate-helpers}
5 | \alias{rate_delay}
6 | \alias{rate_backoff}
7 | \alias{is_rate}
8 | \title{Create delaying rate settings}
9 | \usage{
10 | rate_delay(pause = 1, max_times = Inf)
11 |
12 | rate_backoff(
13 | pause_base = 1,
14 | pause_cap = 60,
15 | pause_min = 1,
16 | max_times = 3,
17 | jitter = TRUE
18 | )
19 |
20 | is_rate(x)
21 | }
22 | \arguments{
23 | \item{pause}{Delay between attempts in seconds.}
24 |
25 | \item{max_times}{Maximum number of requests to attempt.}
26 |
27 | \item{pause_base, pause_cap}{\code{rate_backoff()} uses an exponential
28 | back-off so that each request waits \code{pause_base * 2^i} seconds,
29 | up to a maximum of \code{pause_cap} seconds.}
30 |
31 | \item{pause_min}{Minimum time to wait in the backoff; generally
32 | only necessary if you need pauses less than one second (which may
33 | not be kind to the server, use with caution!).}
34 |
35 | \item{jitter}{Whether to introduce a random jitter in the waiting time.}
36 |
37 | \item{x}{An object to test.}
38 | }
39 | \description{
40 | These helpers create rate settings that you can pass to \code{\link[=insistently]{insistently()}} and
41 | \code{\link[=slowly]{slowly()}}. You can also use them in your own functions with \code{\link[=rate_sleep]{rate_sleep()}}.
42 | }
43 | \examples{
44 | # A delay rate waits the same amount of time:
45 | rate <- rate_delay(0.02)
46 | for (i in 1:3) rate_sleep(rate, quiet = FALSE)
47 |
48 | # A backoff rate waits exponentially longer each time, with random
49 | # jitter by default:
50 | rate <- rate_backoff(pause_base = 0.2, pause_min = 0.005)
51 | for (i in 1:3) rate_sleep(rate, quiet = FALSE)
52 | }
53 |
--------------------------------------------------------------------------------
/man/rate_sleep.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/rate.R
3 | \name{rate_sleep}
4 | \alias{rate_sleep}
5 | \alias{rate_reset}
6 | \title{Wait for a given time}
7 | \usage{
8 | rate_sleep(rate, quiet = TRUE)
9 |
10 | rate_reset(rate)
11 | }
12 | \arguments{
13 | \item{rate}{A \link[=rate_backoff]{rate} object determining the waiting time.}
14 |
15 | \item{quiet}{If \code{FALSE}, prints a message displaying how long until
16 | the next request.}
17 | }
18 | \description{
19 | If the rate's internal counter exceeds the maximum number of times
20 | it is allowed to sleep, \code{rate_sleep()} throws an error of class
21 | \code{purrr_error_rate_excess}.
22 | }
23 | \details{
24 | Call \code{rate_reset()} to reset the internal rate counter to 0.
25 | }
26 | \seealso{
27 | \code{\link[=rate_backoff]{rate_backoff()}}, \code{\link[=insistently]{insistently()}}
28 | }
29 | \keyword{internal}
30 |
--------------------------------------------------------------------------------
/man/rbernoulli.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-utils.R
3 | \name{rbernoulli}
4 | \alias{rbernoulli}
5 | \title{Generate random sample from a Bernoulli distribution}
6 | \usage{
7 | rbernoulli(n, p = 0.5)
8 | }
9 | \arguments{
10 | \item{n}{Number of samples}
11 |
12 | \item{p}{Probability of getting \code{TRUE}}
13 | }
14 | \value{
15 | A logical vector
16 | }
17 | \description{
18 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
19 |
20 | This function was deprecated in purrr 1.0.0 because it's not related to the
21 | core purpose of purrr.
22 | }
23 | \examples{
24 | rbernoulli(10)
25 | rbernoulli(100, 0.1)
26 | }
27 | \keyword{internal}
28 |
--------------------------------------------------------------------------------
/man/rdunif.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-utils.R
3 | \name{rdunif}
4 | \alias{rdunif}
5 | \title{Generate random sample from a discrete uniform distribution}
6 | \usage{
7 | rdunif(n, b, a = 1)
8 | }
9 | \arguments{
10 | \item{n}{Number of samples to draw.}
11 |
12 | \item{a, b}{Range of the distribution (inclusive).}
13 | }
14 | \description{
15 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
16 |
17 | This function was deprecated in purrr 1.0.0 because it's not related to the
18 | core purpose of purrr.
19 | }
20 | \examples{
21 | table(rdunif(1e3, 10))
22 | table(rdunif(1e3, 10, -5))
23 | }
24 | \keyword{internal}
25 |
--------------------------------------------------------------------------------
/man/rerun.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-rerun.R
3 | \name{rerun}
4 | \alias{rerun}
5 | \title{Re-run expressions multiple times}
6 | \usage{
7 | rerun(.n, ...)
8 | }
9 | \arguments{
10 | \item{.n}{Number of times to run expressions}
11 |
12 | \item{...}{Expressions to re-run.}
13 | }
14 | \value{
15 | A list of length \code{.n}. Each element of \code{...} will be
16 | re-run once for each \code{.n}.
17 |
18 | There is one special case: if there's a single unnamed input, the second
19 | level list will be dropped. In this case, \code{rerun(n, x)} behaves like
20 | \code{replicate(n, x, simplify = FALSE)}.
21 | }
22 | \description{
23 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
24 |
25 | This function was deprecated in purrr 1.0.0 because we believe that NSE
26 | functions are not a good fit for purrr. Also, \code{rerun(n, x)} can just as
27 | easily be expressed as \verb{map(1:n, \\(i) x)}
28 |
29 | \code{rerun()} is a convenient way of generating sample data. It works similarly to
30 | \code{\link{replicate}(..., simplify = FALSE)}.
31 | }
32 | \examples{
33 | # old
34 | 5 |> rerun(rnorm(5)) |> str()
35 | # new
36 | 1:5 |> map(\(i) rnorm(5)) |> str()
37 |
38 | # old
39 | 5 |>
40 | rerun(x = rnorm(5), y = rnorm(5)) |>
41 | map_dbl(\(l) cor(l$x, l$y))
42 | # new
43 | 1:5 |>
44 | map(\(i) list(x = rnorm(5), y = rnorm(5))) |>
45 | map_dbl(\(l) cor(l$x, l$y))
46 | }
47 | \keyword{internal}
48 |
--------------------------------------------------------------------------------
/man/safely.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-safely.R
3 | \name{safely}
4 | \alias{safely}
5 | \title{Wrap a function to capture errors}
6 | \usage{
7 | safely(.f, otherwise = NULL, quiet = TRUE)
8 | }
9 | \arguments{
10 | \item{.f}{A function to modify, specified in one of the following ways:
11 | \itemize{
12 | \item A named function, e.g. \code{mean}.
13 | \item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
14 | \item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
15 | compatibility with older versions of R.
16 | }}
17 |
18 | \item{otherwise}{Default value to use when an error occurs.}
19 |
20 | \item{quiet}{Hide errors (\code{TRUE}, the default), or display them
21 | as they occur?}
22 | }
23 | \value{
24 | A function that takes the same arguments as \code{.f}, but returns
25 | a different value, as described above.
26 | }
27 | \description{
28 | Creates a modified version of \code{.f} that always succeeds. It returns a list
29 | with components \code{result} and \code{error}. If the function succeeds, \code{result}
30 | contains the returned value and \code{error} is \code{NULL}. If an error occurred,
31 | \code{error} is an \code{error} object and \code{result} is either \code{NULL} or \code{otherwise}.
32 | }
33 | \section{Adverbs}{
34 | This function is called an adverb because it modifies the effect of a
35 | function (a verb). If you'd like to include a function created an adverb
36 | in a package, be sure to read \link{faq-adverbs-export}.
37 | }
38 |
39 | \examples{
40 | safe_log <- safely(log)
41 | safe_log(10)
42 | safe_log("a")
43 |
44 | list("a", 10, 100) |>
45 | map(safe_log) |>
46 | transpose()
47 |
48 | # This is a bit easier to work with if you supply a default value
49 | # of the same type and use the simplify argument to transpose():
50 | safe_log <- safely(log, otherwise = NA_real_)
51 | list("a", 10, 100) |>
52 | map(safe_log) |>
53 | transpose() |>
54 | simplify_all()
55 | }
56 | \seealso{
57 | Other adverbs:
58 | \code{\link{auto_browse}()},
59 | \code{\link{compose}()},
60 | \code{\link{insistently}()},
61 | \code{\link{negate}()},
62 | \code{\link{partial}()},
63 | \code{\link{possibly}()},
64 | \code{\link{quietly}()},
65 | \code{\link{slowly}()}
66 | }
67 | \concept{adverbs}
68 |
--------------------------------------------------------------------------------
/man/slowly.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/adverb-slowly.R
3 | \name{slowly}
4 | \alias{slowly}
5 | \title{Wrap a function to wait between executions}
6 | \usage{
7 | slowly(f, rate = rate_delay(), quiet = TRUE)
8 | }
9 | \arguments{
10 | \item{f}{A function to modify, specified in one of the following ways:
11 | \itemize{
12 | \item A named function, e.g. \code{mean}.
13 | \item An anonymous function, e.g. \verb{\\(x) x + 1} or \code{function(x) x + 1}.
14 | \item A formula, e.g. \code{~ .x + 1}. Only recommended if you require backward
15 | compatibility with older versions of R.
16 | }}
17 |
18 | \item{rate}{A \link[=rate-helpers]{rate} object. Defaults to a constant delay.}
19 |
20 | \item{quiet}{Hide errors (\code{TRUE}, the default), or display them
21 | as they occur?}
22 | }
23 | \value{
24 | A function that takes the same arguments as \code{.f}, but returns
25 | a different value, as described above.
26 | }
27 | \description{
28 | \code{slowly()} takes a function and modifies it to wait a given
29 | amount of time between each call.
30 | }
31 | \section{Adverbs}{
32 | This function is called an adverb because it modifies the effect of a
33 | function (a verb). If you'd like to include a function created an adverb
34 | in a package, be sure to read \link{faq-adverbs-export}.
35 | }
36 |
37 | \examples{
38 | # For these example, we first create a custom rate
39 | # with a low waiting time between attempts:
40 | rate <- rate_delay(0.1)
41 |
42 | # slowly() causes a function to sleep for a given time between calls:
43 | slow_runif <- slowly(\(x) runif(1), rate = rate, quiet = FALSE)
44 | out <- map(1:5, slow_runif)
45 | }
46 | \seealso{
47 | Other adverbs:
48 | \code{\link{auto_browse}()},
49 | \code{\link{compose}()},
50 | \code{\link{insistently}()},
51 | \code{\link{negate}()},
52 | \code{\link{partial}()},
53 | \code{\link{possibly}()},
54 | \code{\link{quietly}()},
55 | \code{\link{safely}()}
56 | }
57 | \concept{adverbs}
58 |
--------------------------------------------------------------------------------
/man/splice.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-splice.R
3 | \name{splice}
4 | \alias{splice}
5 | \title{Splice objects and lists of objects into a list}
6 | \usage{
7 | splice(...)
8 | }
9 | \arguments{
10 | \item{...}{Objects to concatenate.}
11 | }
12 | \value{
13 | A list.
14 | }
15 | \description{
16 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
17 |
18 | This function was deprecated in purrr 1.0.0 because we no longer believe that
19 | this style of implicit/automatic splicing is a good idea; instead use
20 | \code{rlang::list2()} + \verb{!!!} or \code{\link[=list_flatten]{list_flatten()}}.
21 |
22 | \code{splice()} splices all arguments into a list. Non-list objects and lists
23 | with a S3 class are encapsulated in a list before concatenation.
24 | }
25 | \examples{
26 | inputs <- list(arg1 = "a", arg2 = "b")
27 |
28 | # splice() concatenates the elements of inputs with arg3
29 | splice(inputs, arg3 = c("c1", "c2")) |> str()
30 | list(inputs, arg3 = c("c1", "c2")) |> str()
31 | c(inputs, arg3 = c("c1", "c2")) |> str()
32 | }
33 | \keyword{internal}
34 |
--------------------------------------------------------------------------------
/man/update_list.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/list-modify.R
3 | \name{update_list}
4 | \alias{update_list}
5 | \title{Update a list with formulas}
6 | \usage{
7 | update_list(.x, ...)
8 | }
9 | \arguments{
10 | \item{.x}{List to modify.}
11 |
12 | \item{...}{New values of a list. Use \code{zap()} to remove values.
13 |
14 | These values should be either all named or all unnamed. When
15 | inputs are all named, they are matched to \code{.x} by name. When they
16 | are all unnamed, they are matched by position.
17 |
18 | \link[rlang:dyn-dots]{Dynamic dots} are supported. In particular, if your
19 | replacement values are stored in a list, you can splice that in with
20 | \verb{!!!}.}
21 | }
22 | \description{
23 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
24 |
25 | \code{update_list()} was deprecated in purrr 1.0.0, because we no longer believe
26 | that functions that use NSE are a good fit for purrr.
27 |
28 | \code{update_list()} handles formulas and quosures that can refer to
29 | values existing within the input list. This function is deprecated
30 | because we no longer believe that functions that use tidy evaluation are
31 | a good fit for purrr.
32 | }
33 | \keyword{internal}
34 |
--------------------------------------------------------------------------------
/man/when.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/deprec-when.R
3 | \name{when}
4 | \alias{when}
5 | \title{Match/validate a set of conditions for an object and continue with the action
6 | associated with the first valid match.}
7 | \usage{
8 | when(., ...)
9 | }
10 | \arguments{
11 | \item{.}{the value to match against}
12 |
13 | \item{...}{formulas; each containing a condition as LHS and an action as RHS.
14 | named arguments will define additional values.}
15 | }
16 | \value{
17 | The value resulting from the action of the first valid
18 | match/condition is returned. If no matches are found, and no default is
19 | given, NULL will be returned.
20 |
21 | Validity of the conditions are tested with \code{isTRUE}, or equivalently
22 | with \code{identical(condition, TRUE)}.
23 | In other words conditions resulting in more than one logical will never
24 | be valid. Note that the input value is always treated as a single object,
25 | as opposed to the \code{ifelse} function.
26 | }
27 | \description{
28 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}
29 |
30 | This function was deprecated in purrr 1.0.0 because it's not related to the
31 | core purpose of purrr. You can pull your code out of a pipe and use regular
32 | \code{if}/\verb{else} statements instead.
33 |
34 | \code{when()} is a flavour of pattern matching (or an if-else abstraction) in
35 | which a value is matched against a sequence of condition-action sets. When a
36 | valid match/condition is found the action is executed and the result of the
37 | action is returned.
38 | }
39 | \examples{
40 | 1:10 |>
41 | when(
42 | sum(.) <= 50 ~ sum(.),
43 | sum(.) <= 100 ~ sum(.)/2,
44 | ~ 0
45 | )
46 |
47 | # now
48 | x <- 1:10
49 | if (sum(x) < 10) {
50 | sum(x)
51 | } else if (sum(x) < 100) {
52 | sum(x) / 2
53 | } else {
54 | 0
55 | }
56 | }
57 | \keyword{internal}
58 |
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/purrr/175307f88e110a6d2e1f029df65cd6821625678f/pkgdown/favicon/favicon.ico
--------------------------------------------------------------------------------
/purrr.Rproj:
--------------------------------------------------------------------------------
1 | Version: 1.0
2 | ProjectId: 7599ac37-3c41-46be-af39-1e11a14300d2
3 |
4 | RestoreWorkspace: No
5 | SaveWorkspace: No
6 | AlwaysSaveHistory: Default
7 |
8 | EnableCodeIndexing: Yes
9 | UseSpacesForTab: Yes
10 | NumSpacesForTab: 2
11 | Encoding: UTF-8
12 |
13 | RnwWeave: Sweave
14 | LaTeX: pdfLaTeX
15 |
16 | AutoAppendNewline: Yes
17 | StripTrailingWhitespace: Yes
18 |
19 | BuildType: Package
20 | PackageUseDevtools: Yes
21 | PackageInstallArgs: --no-multiarch --with-keep.source
22 | PackageRoxygenize: rd,collate,namespace
23 |
--------------------------------------------------------------------------------
/revdep/.gitignore:
--------------------------------------------------------------------------------
1 | checks/
2 | logs/
3 | data.sqlite
4 | checks
5 | library
6 | checks.noindex
7 | library.noindex
8 | cloud.noindex
9 | *.html
10 |
--------------------------------------------------------------------------------
/revdep/cran.md:
--------------------------------------------------------------------------------
1 | ## revdepcheck results
2 |
3 | We checked 1943 reverse dependencies (1937 from CRAN + 6 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package.
4 |
5 | * We saw 2 new problems
6 | * We failed to check 45 packages
7 |
8 | Issues with CRAN packages are summarised below.
9 |
10 | ### New problems
11 | (This reports the first line of each new failure)
12 |
13 | * meta
14 | checking installed package size ... NOTE
15 |
16 | * waywiser
17 | checking running R code from vignettes ... ERROR
18 |
19 | ### Failed to check
20 |
21 | * AovBay (NA)
22 | * arealDB (NA)
23 | * autoReg (NA)
24 | * bayesCT (NA)
25 | * bspcov (NA)
26 | * censored (NA)
27 | * CGPfunctions (NA)
28 | * CSCNet (NA)
29 | * dartR.base (NA)
30 | * dartR.popgen (NA)
31 | * deeptrafo (NA)
32 | * DR.SC (NA)
33 | * epizootic (NA)
34 | * GseaVis (NA)
35 | * hettx (NA)
36 | * immcp (NA)
37 | * invivoPKfit (NA)
38 | * jsmodule (NA)
39 | * lnmixsurv (NA)
40 | * lsirm12pl (NA)
41 | * metajam (NA)
42 | * miWQS (NA)
43 | * multinma (NA)
44 | * nesRdata (NA)
45 | * obliqueRSF (NA)
46 | * ontologics (NA)
47 | * OVtool (NA)
48 | * pammtools (NA)
49 | * pathwayTMB (NA)
50 | * pencal (NA)
51 | * quid (NA)
52 | * rdflib (NA)
53 | * robber (NA)
54 | * RVA (NA)
55 | * scCustomize (NA)
56 | * scpi (NA)
57 | * SCpubr (NA)
58 | * SEERaBomb (NA)
59 | * SimplyAgree (NA)
60 | * ssdGSA (NA)
61 | * SSHAARP (NA)
62 | * stabiliser (NA)
63 | * tidyseurat (NA)
64 | * TriDimRegression (NA)
65 | * WRTDStidal (NA)
66 |
--------------------------------------------------------------------------------
/revdep/email.yml:
--------------------------------------------------------------------------------
1 | release_date: ???
2 | rel_release_date: ???
3 | my_news_url: ???
4 | release_version: ???
5 | release_details: ???
6 |
--------------------------------------------------------------------------------
/revdep/problems.md:
--------------------------------------------------------------------------------
1 | # meta
2 |
3 |
4 |
5 | * Version: 8.0-2
6 | * GitHub: https://github.com/guido-s/meta
7 | * Source code: https://github.com/cran/meta
8 | * Date/Publication: 2025-01-21 19:20:02 UTC
9 | * Number of recursive dependencies: 96
10 |
11 | Run `revdepcheck::cloud_details(, "meta")` for more info
12 |
13 |
14 |
15 | ## Newly broken
16 |
17 | * checking installed package size ... NOTE
18 | ```
19 | installed size is 5.6Mb
20 | sub-directories of 1Mb or more:
21 | R 3.5Mb
22 | help 1.5Mb
23 | ```
24 |
25 | ## In both
26 |
27 | * checking Rd cross-references ... NOTE
28 | ```
29 | Packages unavailable to check Rd xrefs: ‘metasens’, ‘robumeta’
30 | ```
31 |
32 | # waywiser
33 |
34 |
35 |
36 | * Version: 0.6.0
37 | * GitHub: https://github.com/ropensci/waywiser
38 | * Source code: https://github.com/cran/waywiser
39 | * Date/Publication: 2024-06-27 19:10:03 UTC
40 | * Number of recursive dependencies: 172
41 |
42 | Run `revdepcheck::cloud_details(, "waywiser")` for more info
43 |
44 |
45 |
46 | ## Newly broken
47 |
48 | * checking running R code from vignettes ... ERROR
49 | ```
50 | Errors in running code in vignettes:
51 | when running code in ‘multi-scale-assessment.Rmd’
52 | ...
53 | |
54 | |================= | 25%
55 | |
56 | |================== | 25%Warning in unzip(file_loc, exdir = tmp) :
57 | error 1 in extracting from zip file
58 | Cannot open layer tl_2022_us_county
59 |
60 | When sourcing ‘multi-scale-assessment.R’:
61 | Error: Opening layer failed.
62 | Execution halted
63 |
64 | ‘multi-scale-assessment.Rmd’ using ‘UTF-8’... failed
65 | ‘residual-autocorrelation.Rmd’ using ‘UTF-8’... OK
66 | ‘waywiser.Rmd’ using ‘UTF-8’... OK
67 | ```
68 |
69 | ## In both
70 |
71 | * checking data for non-ASCII characters ... NOTE
72 | ```
73 | Note: found 1 marked UTF-8 string
74 | ```
75 |
76 |
--------------------------------------------------------------------------------
/src/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.so
3 | *.dll
4 |
--------------------------------------------------------------------------------
/src/Makevars:
--------------------------------------------------------------------------------
1 | PKG_CFLAGS = $(C_VISIBILITY)
2 |
--------------------------------------------------------------------------------
/src/backports.c:
--------------------------------------------------------------------------------
1 | #define R_NO_REMAP
2 | #include
3 | #include
4 | #include
5 |
6 | #if defined(R_VERSION) && R_VERSION < R_Version(3, 2, 0)
7 | SEXP Rf_installChar(SEXP x) {
8 | return Rf_install(CHAR(x));
9 | }
10 | #endif
11 |
12 | #if defined(R_VERSION) && R_VERSION < R_Version(4, 5, 0)
13 | SEXP R_mkClosure(SEXP formals, SEXP body, SEXP env) {
14 | SEXP fun = Rf_allocSExp(CLOSXP);
15 | SET_FORMALS(fun, formals);
16 | SET_BODY(fun, body);
17 | SET_CLOENV(fun, env);
18 | return fun;
19 | }
20 | #endif
21 |
--------------------------------------------------------------------------------
/src/backports.h:
--------------------------------------------------------------------------------
1 | #ifndef BACKPORTS_H
2 | #define BACKPORTS_H
3 |
4 | #include
5 |
6 | #if defined(R_VERSION) && R_VERSION < R_Version(3, 2, 0)
7 | SEXP Rf_installChar(SEXP);
8 | #endif
9 |
10 | #if defined(R_VERSION) && R_VERSION < R_Version(4, 5, 0)
11 | SEXP R_mkClosure(SEXP, SEXP, SEXP);
12 | #endif
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/src/cleancall.h:
--------------------------------------------------------------------------------
1 | #ifndef CLEANCALL_H
2 | #define CLEANCALL_H
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #ifdef __cplusplus
9 | extern "C" {
10 | #endif
11 |
12 | // --------------------------------------------------------------------
13 | // Internals
14 | // --------------------------------------------------------------------
15 |
16 | typedef union {void* p; DL_FUNC fn;} fn_ptr;
17 |
18 | #if (defined(R_VERSION) && R_VERSION < R_Version(3, 4, 0))
19 | SEXP R_MakeExternalPtrFn(DL_FUNC p, SEXP tag, SEXP prot);
20 | DL_FUNC R_ExternalPtrAddrFn(SEXP s);
21 | #endif
22 |
23 | // --------------------------------------------------------------------
24 | // API for packages that embed cleancall
25 | // --------------------------------------------------------------------
26 |
27 | // The R API does not have a setter for external function pointers
28 | SEXP cleancall_MakeExternalPtrFn(DL_FUNC p, SEXP tag, SEXP prot);
29 | void cleancall_SetExternalPtrAddrFn(SEXP s, DL_FUNC p);
30 |
31 | #define CLEANCALL_METHOD_RECORD \
32 | {"cleancall_call", (DL_FUNC) &cleancall_call, 2}
33 |
34 | SEXP cleancall_call(SEXP args, SEXP env);
35 | void cleancall_init(void);
36 |
37 | // --------------------------------------------------------------------
38 | // Public API
39 | // --------------------------------------------------------------------
40 |
41 | #define R_CLEANCALL_SUPPORT 1
42 |
43 | SEXP r_with_cleanup_context(SEXP (*fn)(void* data), void* data);
44 | void r_call_on_exit(void (*fn)(void* data), void* data);
45 | void r_call_on_early_exit(void (*fn)(void* data), void* data);
46 |
47 | #ifdef __cplusplus
48 | }
49 | #endif
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/src/coerce.h:
--------------------------------------------------------------------------------
1 | #ifndef COERCE_H
2 | #define COERCE_H
3 |
4 | // Set value of to[i] to from[j], coercing vectors using usual rules.
5 | void set_vector_value(SEXP to, int i, SEXP from, int j);
6 |
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/src/conditions.h:
--------------------------------------------------------------------------------
1 | #ifndef CONDITIONS_H
2 | #define CONDITIONS_H
3 |
4 | #include
5 |
6 | void __attribute__ ((noreturn)) stop_bad_type(SEXP x, const char* expected, const char* what, const char* arg) __attribute__((noreturn));
7 | void __attribute__ ((noreturn)) stop_bad_element_type(SEXP x, R_xlen_t index, const char* expected, const char* what, const char* arg) __attribute__((noreturn));
8 | void __attribute__ ((noreturn)) stop_bad_element_length(SEXP x, R_xlen_t index, R_xlen_t expected_length, const char* what, const char* arg, bool recycle) __attribute__((noreturn));
9 | SEXP current_env(void);
10 | void __attribute__ ((noreturn)) r_abort(const char* fmt, ...);
11 | void __attribute__ ((noreturn)) r_abort_call(SEXP env, const char* fmt, ...);
12 |
13 | const char* rlang_obj_type_friendly_full(SEXP x, bool value, bool length);
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/src/init.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include // for NULL
4 | #include
5 |
6 | // Compile with `-fvisibility=hidden -DHAVE_VISIBILITY_ATTRIBUTE` if you link to this library
7 | #include
8 | #define export attribute_visible extern
9 |
10 | #include "cleancall.h"
11 |
12 | /* .Call calls */
13 | extern SEXP coerce_impl(SEXP, SEXP);
14 | extern SEXP pluck_impl(SEXP, SEXP, SEXP, SEXP);
15 | extern SEXP flatten_impl(SEXP);
16 | extern SEXP map_impl(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
17 | extern SEXP map2_impl(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
18 | extern SEXP pmap_impl(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP, SEXP);
19 | extern SEXP transpose_impl(SEXP, SEXP);
20 | extern SEXP vflatten_impl(SEXP, SEXP);
21 |
22 | static const R_CallMethodDef CallEntries[] = {
23 | CLEANCALL_METHOD_RECORD,
24 | {"coerce_impl", (DL_FUNC) &coerce_impl, 2},
25 | {"pluck_impl", (DL_FUNC) &pluck_impl, 4},
26 | {"flatten_impl", (DL_FUNC) &flatten_impl, 1},
27 | {"map_impl", (DL_FUNC) &map_impl, 6},
28 | {"map2_impl", (DL_FUNC) &map2_impl, 6},
29 | {"pmap_impl", (DL_FUNC) &pmap_impl, 8},
30 | {"transpose_impl", (DL_FUNC) &transpose_impl, 2},
31 | {"vflatten_impl", (DL_FUNC) &vflatten_impl, 2},
32 | {"purrr_eval", (DL_FUNC) &Rf_eval, 2},
33 | {NULL, NULL, 0}
34 | };
35 |
36 | export void R_init_purrr(DllInfo *dll)
37 | {
38 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
39 | R_useDynamicSymbols(dll, FALSE);
40 | cleancall_init();
41 | }
42 |
--------------------------------------------------------------------------------
/src/map.h:
--------------------------------------------------------------------------------
1 | #ifndef MAP_H
2 | #define MAP_H
3 |
4 | extern "C" {
5 | SEXP map_impl(SEXP env,
6 | SEXP ffi_type,
7 | SEXP progress,
8 | SEXP ffi_n,
9 | SEXP names,
10 | SEXP i);
11 |
12 | SEXP pmap_impl(SEXP env,
13 | SEXP ffi_type,
14 | SEXP progress,
15 | SEXP ffi_n,
16 | SEXP names,
17 | SEXP i,
18 | SEXP call_names,
19 | SEXP ffi_call_n);
20 | }
21 |
22 | #endif
23 |
--------------------------------------------------------------------------------
/src/utils.c:
--------------------------------------------------------------------------------
1 | #define R_NO_REMAP
2 | #include
3 | #include
4 |
5 | SEXP sym_protect(SEXP x) {
6 | if (TYPEOF(x) == LANGSXP || TYPEOF(x) == SYMSXP) {
7 | SEXP quote_prim = Rf_eval(Rf_install("quote"), R_BaseEnv);
8 | return(Rf_lang2(quote_prim, x));
9 | } else {
10 | return x;
11 | }
12 | }
13 |
14 | bool is_vector(SEXP x) {
15 | switch (TYPEOF(x)) {
16 | case LGLSXP:
17 | case INTSXP:
18 | case REALSXP:
19 | case CPLXSXP:
20 | case STRSXP:
21 | case RAWSXP:
22 | case VECSXP:
23 | return true;
24 | default:
25 | return false;
26 | }
27 | }
28 |
29 | SEXP list6(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x) {
30 | PROTECT(s);
31 | s = Rf_cons(s, Rf_list5(t, u, v, w, x));
32 | UNPROTECT(1);
33 | return s;
34 | }
35 |
36 | SEXP lang7(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x, SEXP y) {
37 | PROTECT(s);
38 | s = Rf_lcons(s, list6(t, u, v, w, x, y));
39 | UNPROTECT(1);
40 | return s;
41 | }
42 | SEXP list7(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x, SEXP y) {
43 | PROTECT(s);
44 | s = Rf_cons(s, list6(t, u, v, w, x, y));
45 | UNPROTECT(1);
46 | return s;
47 | }
48 | SEXP lang8(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x, SEXP y, SEXP z) {
49 | PROTECT(s);
50 | s = Rf_lcons(s, list7(t, u, v, w, x, y, z));
51 | UNPROTECT(1);
52 | return s;
53 | }
54 |
--------------------------------------------------------------------------------
/src/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef UTILS_H
2 | #define UTILS_H
3 |
4 | #include
5 |
6 |
7 | SEXP sym_protect(SEXP x);
8 |
9 | bool is_vector(SEXP x);
10 |
11 | SEXP lang7(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x, SEXP y);
12 | SEXP lang8(SEXP s, SEXP t, SEXP u, SEXP v, SEXP w, SEXP x, SEXP y, SEXP z);
13 |
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(purrr)
3 |
4 | test_check("purrr")
5 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/adverb-auto-browse.md:
--------------------------------------------------------------------------------
1 | # auto_browse() not intended for primitive functions
2 |
3 | Code
4 | auto_browse(log)(NULL)
5 | Condition
6 | Error in `auto_browse()`:
7 | ! `.f` must not be a primitive function.
8 |
9 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/adverb-compose.md:
--------------------------------------------------------------------------------
1 | # composed function prints informatively
2 |
3 | Code
4 | # Single input
5 | compose(fn1)
6 | Output
7 |
8 | 1. function(x) x + 1
9 | Code
10 | # Multiple inputs
11 | compose(fn1, fn2)
12 | Output
13 |
14 | 1. function(x) x / 1
15 |
16 | 2. function(x) x + 1
17 |
18 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/adverb-insistently.md:
--------------------------------------------------------------------------------
1 | # insistently() resets rate state
2 |
3 | Request failed after 0 attempts.
4 |
5 | ---
6 |
7 | Request failed after 0 attempts.
8 |
9 | # validates inputs
10 |
11 | Code
12 | insistently(mean, 10)
13 | Condition
14 | Error in `insistently()`:
15 | ! `rate` must be a rate object, not a number.
16 |
17 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/adverb-partial.md:
--------------------------------------------------------------------------------
1 | # partial() squashes quosures before printing
2 |
3 | Code
4 | foo
5 | Output
6 |
7 | function (...)
8 | foo(y = 3, ...)
9 |
10 | # `.lazy`, `.env`, and `.first` are soft-deprecated
11 |
12 | Code
13 | . <- partial(list, "foo", .lazy = TRUE)
14 | Condition
15 | Warning:
16 | The `.lazy` argument of `partial()` is deprecated as of purrr 0.3.0.
17 | Code
18 | . <- partial(list, "foo", .env = env())
19 | Condition
20 | Warning:
21 | The `.env` argument of `partial()` is deprecated as of purrr 0.3.0.
22 | Code
23 | . <- partial(list, "foo", .first = TRUE)
24 | Condition
25 | Warning:
26 | The `.first` argument of `partial()` is deprecated as of purrr 0.3.0.
27 |
28 | # checks inputs
29 |
30 | Code
31 | partial(1)
32 | Condition
33 | Error in `partial()`:
34 | ! `.f` must be a function, not a number.
35 |
36 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/adverb-slowly.md:
--------------------------------------------------------------------------------
1 | # validates inputs
2 |
3 | Code
4 | slowly(mean, 10)
5 | Condition
6 | Error in `slowly()`:
7 | ! `rate` must be a rate object, not a number.
8 |
9 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/arrays.md:
--------------------------------------------------------------------------------
1 | # array_branch throws an error for wrong margins on a vector
2 |
3 | Code
4 | array_branch(1:3, 2)
5 | Condition
6 | Error in `array_branch()`:
7 | ! `margin` must be `NULL` or `1` with 1D arrays, not "2".
8 |
9 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/conditions.md:
--------------------------------------------------------------------------------
1 | # stop_bad_type() constructs default `what`
2 |
3 | Code
4 | stop_bad_type(NA, "`NULL`")
5 | Condition
6 | Error:
7 | ! Object must be `NULL`, not `NA`.
8 |
9 | ---
10 |
11 | Code
12 | stop_bad_type(NA, "`NULL`", arg = ".foo")
13 | Condition
14 | Error:
15 | ! `.foo` must be `NULL`, not `NA`.
16 |
17 | ---
18 |
19 | Code
20 | stop_bad_type(NA, "`NULL`", arg = quote(.foo))
21 | Condition
22 | Error in `what_bad_object()`:
23 | ! `arg` must be `NULL` or a string, not a symbol.
24 |
25 | # stop_bad_element_type() constructs type errors
26 |
27 | Code
28 | stop_bad_element_type(1:3, 3, "a foobaz")
29 | Condition
30 | Error:
31 | ! Element 3 must be a foobaz, not an integer vector.
32 |
33 | ---
34 |
35 | Code
36 | stop_bad_element_type(1:3, 3, "a foobaz", actual = "a quux")
37 | Condition
38 | Error:
39 | ! Element 3 must be a foobaz, not an integer vector.
40 |
41 | ---
42 |
43 | Code
44 | stop_bad_element_type(1:3, 3, "a foobaz", arg = "..arg")
45 | Condition
46 | Error:
47 | ! `..arg[[3]]` must be a foobaz, not an integer vector.
48 |
49 | # stop_bad_element_type() accepts `what`
50 |
51 | Code
52 | stop_bad_element_type(1:3, 3, "a foobaz", what = "Result")
53 | Condition
54 | Error:
55 | ! Result 3 must be a foobaz, not an integer vector.
56 |
57 | # stop_bad_element_length() constructs error message
58 |
59 | Code
60 | stop_bad_element_length(1:3, 8, 10)
61 | Condition
62 | Error:
63 | ! Element 8 must have length 10, not 3.
64 |
65 | ---
66 |
67 | Code
68 | stop_bad_element_length(1:3, 8, 10, arg = ".foo")
69 | Condition
70 | Error:
71 | ! `.foo[[8]]` must have length 10, not 3.
72 |
73 | ---
74 |
75 | Code
76 | stop_bad_element_length(1:3, 8, 10, arg = ".foo", what = "Result")
77 | Condition
78 | Error:
79 | ! `.foo[[8]]` must have length 10, not 3.
80 |
81 | ---
82 |
83 | Code
84 | stop_bad_element_length(1:3, 8, 10, arg = ".foo", what = "Result", recycle = TRUE)
85 | Condition
86 | Error:
87 | ! `.foo[[8]]` must have length 1 or 10, not 3.
88 |
89 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-along.md:
--------------------------------------------------------------------------------
1 | # list-along is deprecated
2 |
3 | Code
4 | . <- list_along(1:4)
5 | Condition
6 | Warning:
7 | `list_along()` was deprecated in purrr 1.0.0.
8 | i Please use rep_along(x, list()) instead.
9 |
10 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-cross.md:
--------------------------------------------------------------------------------
1 | # filtering requires a predicate function
2 |
3 | Code
4 | cross2(1:3, 1:3, .filter = ~ c(TRUE, TRUE))
5 | Condition
6 | Error in `cross()`:
7 | ! The filter function must return a single `TRUE` or `FALSE`, not a logical vector.
8 |
9 | # filtering fails when filter function doesn't return a logical
10 |
11 | Code
12 | cross3(1:3, 1:3, 1:3, .filter = filter)
13 | Condition
14 | Error in `cross()`:
15 | ! The filter function must return a single `TRUE` or `FALSE`, not an integer.
16 |
17 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-invoke.md:
--------------------------------------------------------------------------------
1 | # invoke_* is deprecated
2 |
3 | Code
4 | . <- invoke(identity, 1)
5 | Condition
6 | Warning:
7 | `invoke()` was deprecated in purrr 1.0.0.
8 | i Please use `exec()` instead.
9 | Code
10 | . <- invoke_map(identity, list())
11 | Condition
12 | Warning:
13 | `invoke_map()` was deprecated in purrr 1.0.0.
14 | i Please use map() + exec() instead.
15 | Code
16 | . <- invoke_map_lgl(identity, list())
17 | Condition
18 | Warning:
19 | `invoke_lgl()` was deprecated in purrr 1.0.0.
20 | i Please use map_lgl() + exec() instead.
21 | Code
22 | . <- invoke_map_int(identity, list())
23 | Condition
24 | Warning:
25 | `invoke_int()` was deprecated in purrr 1.0.0.
26 | i Please use map_int() + exec() instead.
27 | Code
28 | . <- invoke_map_dbl(identity, list())
29 | Condition
30 | Warning:
31 | `invoke_dbl()` was deprecated in purrr 1.0.0.
32 | i Please use map_dbl() + exec() instead.
33 | Code
34 | . <- invoke_map_chr(identity, list())
35 | Condition
36 | Warning:
37 | `invoke_chr()` was deprecated in purrr 1.0.0.
38 | i Please use map_chr() + exec() instead.
39 | Code
40 | . <- invoke_map_raw(identity, list())
41 | Condition
42 | Warning:
43 | `invoke_raw()` was deprecated in purrr 1.0.0.
44 | i Please use map_raw() + exec() instead.
45 |
46 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-lift.md:
--------------------------------------------------------------------------------
1 | # lift functions are deprecated
2 |
3 | Code
4 | . <- lift_dl(function() { })
5 | Condition
6 | Warning:
7 | `lift()` was deprecated in purrr 1.0.0.
8 | Code
9 | . <- lift_dv(function() { })
10 | Condition
11 | Warning:
12 | `lift_dv()` was deprecated in purrr 1.0.0.
13 | Code
14 | . <- lift_vl(function() { })
15 | Condition
16 | Warning:
17 | `lift_vl()` was deprecated in purrr 1.0.0.
18 | Code
19 | . <- lift_vd(function() { })
20 | Condition
21 | Warning:
22 | `lift_vd()` was deprecated in purrr 1.0.0.
23 | Code
24 | . <- lift_ld(function() { })
25 | Condition
26 | Warning:
27 | `lift_ld()` was deprecated in purrr 1.0.0.
28 | Code
29 | . <- lift_lv(function() { })
30 | Condition
31 | Warning:
32 | `lift_lv()` was deprecated in purrr 1.0.0.
33 |
34 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-map.md:
--------------------------------------------------------------------------------
1 | # at_depth is defunct
2 |
3 | Code
4 | at_depth()
5 | Condition
6 | Error:
7 | ! `at_depth()` was deprecated in purrr 0.3.0 and is now defunct.
8 | i Please use `map_depth()` instead.
9 |
10 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-prepend.md:
--------------------------------------------------------------------------------
1 | # prepend is deprecated
2 |
3 | Code
4 | . <- prepend(1, 2)
5 | Condition
6 | Warning:
7 | `prepend()` was deprecated in purrr 1.0.0.
8 | i Please use append(after = 0) instead.
9 |
10 | # prepend throws error if before param is neither NULL nor between 1 and length(x)
11 |
12 | Code
13 | prepend(list(), 1, before = 1)
14 | Condition
15 | Error in `prepend()`:
16 | ! is.null(before) || (before > 0 && before <= n) is not TRUE
17 |
18 | ---
19 |
20 | Code
21 | x %>% prepend(4, before = 0)
22 | Condition
23 | Error in `prepend()`:
24 | ! is.null(before) || (before > 0 && before <= n) is not TRUE
25 |
26 | ---
27 |
28 | Code
29 | x %>% prepend(4, before = 4)
30 | Condition
31 | Error in `prepend()`:
32 | ! is.null(before) || (before > 0 && before <= n) is not TRUE
33 |
34 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-rerun.md:
--------------------------------------------------------------------------------
1 | # is deprecated
2 |
3 | Code
4 | . <- rerun(5, rnorm(1))
5 | Condition
6 | Warning:
7 | `rerun()` was deprecated in purrr 1.0.0.
8 | i Please use `map()` instead.
9 | # Previously
10 | rerun(5, rnorm(1))
11 |
12 | # Now
13 | map(1:5, ~ rnorm(1))
14 | Code
15 | . <- rerun(5, rnorm(1), rnorm(2))
16 | Condition
17 | Warning:
18 | `rerun()` was deprecated in purrr 1.0.0.
19 | i Please use `map()` instead.
20 | # Previously
21 | rerun(5, rnorm(1), rnorm(2))
22 |
23 | # Now
24 | map(1:5, ~ list(rnorm(1), rnorm(2)))
25 |
26 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-splice.md:
--------------------------------------------------------------------------------
1 | # splice is deprecated
2 |
3 | Code
4 | . <- splice()
5 | Condition
6 | Warning:
7 | `splice()` was deprecated in purrr 1.0.0.
8 | i Please use `list_flatten()` instead.
9 |
10 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-utils.md:
--------------------------------------------------------------------------------
1 | # rdunif and rbernoulli are deprecated
2 |
3 | Code
4 | . <- rdunif(10, 1)
5 | Condition
6 | Warning:
7 | `rdunif()` was deprecated in purrr 1.0.0.
8 | Code
9 | . <- rbernoulli(10)
10 | Condition
11 | Warning:
12 | `rbernoulli()` was deprecated in purrr 1.0.0.
13 |
14 | # rdunif fails if a and b are not unit length numbers
15 |
16 | Code
17 | rdunif(1000, 1, "a")
18 | Condition
19 | Error in `rdunif()`:
20 | ! is.numeric(a) is not TRUE
21 |
22 | ---
23 |
24 | Code
25 | rdunif(1000, 1, c(0.5, 0.2))
26 | Condition
27 | Error in `rdunif()`:
28 | ! length(a) == 1 is not TRUE
29 |
30 | ---
31 |
32 | Code
33 | rdunif(1000, FALSE, 2)
34 | Condition
35 | Error in `rdunif()`:
36 | ! is.numeric(b) is not TRUE
37 |
38 | ---
39 |
40 | Code
41 | rdunif(1000, c(2, 3), 2)
42 | Condition
43 | Error in `rdunif()`:
44 | ! length(b) == 1 is not TRUE
45 |
46 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/deprec-when.md:
--------------------------------------------------------------------------------
1 | # when is deprecated
2 |
3 | Code
4 | . <- when(1:5 < 3 ~ 1, ~0)
5 | Condition
6 | Warning:
7 | `when()` was deprecated in purrr 1.0.0.
8 | i Please use `if` instead.
9 |
10 | # error when named arguments have no matching conditions
11 |
12 | Code
13 | 1:5 %>% when(a = sum(.) < 5 ~ 3)
14 | Condition
15 | Error in `when()`:
16 | ! At least one matching condition is needed.
17 |
18 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/detect.md:
--------------------------------------------------------------------------------
1 | # `detect()` requires a predicate function
2 |
3 | Code
4 | detect(list(1:2, 2), is.na)
5 | Condition
6 | Error in `detect()`:
7 | ! `.f()` must return a single `TRUE` or `FALSE`, not a logical vector.
8 |
9 | ---
10 |
11 | Code
12 | detect_index(list(1:2, 2), is.na)
13 | Condition
14 | Error in `detect_index()`:
15 | ! `.f()` must return a single `TRUE` or `FALSE`, not a logical vector.
16 |
17 | # `.right` argument is retired
18 |
19 | Code
20 | . <- detect(1:2, ~TRUE, .right = TRUE)
21 | Condition
22 | Warning:
23 | The `.right` argument of `detect()` is deprecated as of purrr 0.3.0.
24 | i Please use the `.dir` argument instead.
25 | Code
26 | . <- detect_index(1:2, ~TRUE, .right = TRUE)
27 | Condition
28 | Warning:
29 | The `.right` argument of `detect_index()` is deprecated as of purrr 0.3.0.
30 | i Please use the `.dir` argument instead.
31 |
32 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/every-some-none.md:
--------------------------------------------------------------------------------
1 | # every() requires logical value
2 |
3 | Code
4 | every(list(1:3), identity)
5 | Condition
6 | Error in `every()`:
7 | ! `.p()` must return a single `TRUE` or `FALSE`, not an integer vector.
8 |
9 | ---
10 |
11 | Code
12 | every(list(function() NULL), identity)
13 | Condition
14 | Error in `every()`:
15 | ! `.p()` must return a single `TRUE` or `FALSE`, not a function.
16 |
17 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/head-tail.md:
--------------------------------------------------------------------------------
1 | # head_while and tail_while require predicate function
2 |
3 | Code
4 | head_while(1:3, ~NA)
5 | Condition
6 | Error in `head_while()`:
7 | ! `.p()` must return a single `TRUE` or `FALSE`, not `NA`.
8 |
9 | ---
10 |
11 | Code
12 | tail_while(1:3, ~ c(TRUE, FALSE))
13 | Condition
14 | Error in `tail_while()`:
15 | ! `.p()` must return a single `TRUE` or `FALSE`, not a logical vector.
16 |
17 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/keep.md:
--------------------------------------------------------------------------------
1 | # keep() and discard() require predicate functions
2 |
3 | Code
4 | keep(1:3, ~NA)
5 | Condition
6 | Error in `keep()`:
7 | i In index: 1.
8 | Caused by error:
9 | ! `.p()` must return a single `TRUE` or `FALSE`, not `NA`.
10 | Code
11 | discard(1:3, ~NA)
12 | Condition
13 | Error in `discard()`:
14 | i In index: 1.
15 | Caused by error:
16 | ! `.p()` must return a single `TRUE` or `FALSE`, not `NA`.
17 |
18 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/list-flatten.md:
--------------------------------------------------------------------------------
1 | # requires a list
2 |
3 | Code
4 | list_flatten(1:2)
5 | Condition
6 | Error in `list_flatten()`:
7 | ! `x` must be a list, not an integer vector.
8 |
9 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/list-modify.md:
--------------------------------------------------------------------------------
1 | # list_modify() validates inputs
2 |
3 | Code
4 | list_modify(1:3)
5 | Condition
6 | Error in `list_modify()`:
7 | ! `.x` must be a list, not an integer vector.
8 |
9 | ---
10 |
11 | Code
12 | list_modify(list(a = 1), 2, a = 2)
13 | Condition
14 | Error in `list_modify()`:
15 | ! `...` arguments must be either all named or all unnamed.
16 |
17 | ---
18 |
19 | Code
20 | list_modify(list(x = 1), x = 2, x = 3)
21 | Condition
22 | Error in `list_modify()`:
23 | ! Arguments in `...` must have unique names.
24 | x Multiple arguments named `x` at positions 1 and 2.
25 |
26 | # merge() validates inputs
27 |
28 | Code
29 | list_merge(1:3)
30 | Condition
31 | Error in `list_merge()`:
32 | ! `.x` must be a list, not an integer vector.
33 |
34 | ---
35 |
36 | Code
37 | list_merge(list(x = 1), x = 2, x = 3)
38 | Condition
39 | Error in `list_merge()`:
40 | ! Arguments in `...` must have unique names.
41 | x Multiple arguments named `x` at positions 1 and 2.
42 |
43 | # update_list() is deprecated
44 |
45 | Code
46 | . <- update_list(list())
47 | Condition
48 | Warning:
49 | `update_list()` was deprecated in purrr 1.0.0.
50 |
51 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/list-simplify.md:
--------------------------------------------------------------------------------
1 | # ptype is enforced
2 |
3 | Code
4 | list_simplify(list(1, 2), ptype = character())
5 | Condition
6 | Error in `list_simplify()`:
7 | ! Can't convert `[[1]]` to .
8 |
9 | ---
10 |
11 | Code
12 | list_simplify(list(1, 2), ptype = character(), strict = FALSE)
13 | Condition
14 | Error in `list_simplify()`:
15 | ! Can't convert `[[1]]` to .
16 |
17 | # strict simplification will error
18 |
19 | Code
20 | list_simplify(list(mean))
21 | Condition
22 | Error in `list_simplify()`:
23 | ! `x[[1]]` must be a vector, not a function.
24 | Code
25 | list_simplify(list(1, "a"))
26 | Condition
27 | Error in `list_simplify()`:
28 | ! Can't combine `[[1]]` and `[[2]]` .
29 | Code
30 | list_simplify(list(1, 1:2))
31 | Condition
32 | Error in `list_simplify()`:
33 | ! `x[[2]]` must have size 1, not size 2.
34 | Code
35 | list_simplify(list(data.frame(x = 1), data.frame(x = 1:2)))
36 | Condition
37 | Error in `list_simplify()`:
38 | ! `x[[2]]` must have size 1, not size 2.
39 | Code
40 | list_simplify(list(1, 2), ptype = character())
41 | Condition
42 | Error in `list_simplify()`:
43 | ! Can't convert `[[1]]` to .
44 |
45 | # list_simplify() validates inputs
46 |
47 | Code
48 | list_simplify(1:5)
49 | Condition
50 | Error in `list_simplify()`:
51 | ! `x` must be a list, not an integer vector.
52 |
53 | ---
54 |
55 | Code
56 | list_simplify(list(), strict = NA)
57 | Condition
58 | Error in `list_simplify()`:
59 | ! `strict` must be `TRUE` or `FALSE`, not `NA`.
60 |
61 | # list_simplify_internal() validates inputs
62 |
63 | Code
64 | list_simplify_internal(list(), simplify = 1)
65 | Condition
66 | Error:
67 | ! `simplify` must be `TRUE`, `FALSE`, or `NA`, not the number 1.
68 |
69 | ---
70 |
71 | Code
72 | list_simplify_internal(list(), simplify = FALSE, ptype = integer())
73 | Condition
74 | Error:
75 | ! Can't specify `ptype` when `simplify = FALSE`.
76 |
77 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/lmap.md:
--------------------------------------------------------------------------------
1 | # validates inputs
2 |
3 | Code
4 | lmap(list(1), ~1)
5 | Condition
6 | Error in `lmap()`:
7 | ! `.f(.x[[1]])` must return a list, not a number.
8 | Code
9 | lmap(list(1), environment())
10 | Condition
11 | Error in `lmap()`:
12 | ! Can't convert `.f`, an environment, to a function.
13 | Code
14 | lmap(list(1), ~1, .else = environment())
15 | Condition
16 | Error in `lmap()`:
17 | ! Can't convert `.else`, an environment, to a function.
18 |
19 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/map-depth.md:
--------------------------------------------------------------------------------
1 | # map_depth modifies values at specified depth
2 |
3 | Code
4 | map_depth(x1, 6, length)
5 | Condition
6 | Error in `.fmap()`:
7 | i In index: 1.
8 | Caused by error in `.fmap()`:
9 | i In index: 1.
10 | Caused by error in `.fmap()`:
11 | i In index: 1.
12 | Caused by error in `map_depth()`:
13 | ! List not deep enough
14 |
15 | ---
16 |
17 | Code
18 | map_depth(x1, -5, length)
19 | Condition
20 | Error in `map_depth()`:
21 | ! Negative `.depth` (-5) must be greater than -4.
22 |
23 | # default doesn't recurse into data frames, but can customise
24 |
25 | Code
26 | map_depth(x, 2, class)
27 | Condition
28 | Error in `.fmap()`:
29 | i In index: 1.
30 | Caused by error in `map_depth()`:
31 | ! List not deep enough
32 |
33 | # modify_depth modifies values at specified depth
34 |
35 | Code
36 | modify_depth(x1, 5, length)
37 | Condition
38 | Error in `map()`:
39 | i In index: 1.
40 | Caused by error in `map()`:
41 | i In index: 1.
42 | Caused by error in `map()`:
43 | i In index: 1.
44 | Caused by error in `modify_depth()`:
45 | ! List not deep enough
46 |
47 | ---
48 |
49 | Code
50 | modify_depth(x1, -5, length)
51 | Condition
52 | Error in `modify_depth()`:
53 | ! Negative `.depth` (-5) must be greater than -4.
54 |
55 | # vectorised operations on the recursive and atomic levels yield same results
56 |
57 | Code
58 | modify_depth(x, 5, `+`, 10L)
59 | Condition
60 | Error in `map()`:
61 | i In index: 1.
62 | Caused by error in `map()`:
63 | i In index: 1.
64 | Caused by error in `map()`:
65 | i In index: 1.
66 | Caused by error in `modify_depth()`:
67 | ! List not deep enough
68 |
69 | # validates depth
70 |
71 | Code
72 | check_depth(mean)
73 | Condition
74 | Error:
75 | ! `depth` must be a whole number, not a function.
76 |
77 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/map-if-at.md:
--------------------------------------------------------------------------------
1 | # map_if requires predicate functions
2 |
3 | Code
4 | map_if(1:3, ~NA, ~"foo")
5 | Condition
6 | Error in `map_if()`:
7 | i In index: 1.
8 | Caused by error:
9 | ! `.p()` must return a single `TRUE` or `FALSE`, not `NA`.
10 |
11 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/map-raw.md:
--------------------------------------------------------------------------------
1 | # _raw funtions are deprecated
2 |
3 | Code
4 | . <- map_raw(list(), ~.x)
5 | Condition
6 | Warning:
7 | `map_raw()` was deprecated in purrr 1.0.0.
8 | i Please use `map_vec()` instead.
9 | Code
10 | . <- map2_raw(list(), list(), ~.x)
11 | Condition
12 | Warning:
13 | `map2_raw()` was deprecated in purrr 1.0.0.
14 | i Please use `map2_vec()` instead.
15 | Code
16 | . <- imap_raw(list(), ~.x)
17 | Condition
18 | Warning:
19 | `imap_raw()` was deprecated in purrr 1.0.0.
20 | i Please use `imap_vec()` instead.
21 | Code
22 | . <- pmap_raw(list(), ~.x)
23 | Condition
24 | Warning:
25 | `pmap_raw()` was deprecated in purrr 1.0.0.
26 | i Please use `pmap_vec()` instead.
27 | Code
28 | . <- flatten_raw(list())
29 | Condition
30 | Warning:
31 | `flatten_raw()` was deprecated in purrr 1.0.0.
32 |
33 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/map.md:
--------------------------------------------------------------------------------
1 | # fails on non-vectors
2 |
3 | Code
4 | map(environment(), identity)
5 | Condition
6 | Error in `map()`:
7 | ! `.x` must be a vector, not an environment.
8 |
9 | ---
10 |
11 | Code
12 | map(quote(a), identity)
13 | Condition
14 | Error in `map()`:
15 | ! `.x` must be a vector, not a symbol.
16 |
17 | # all inform about location of problem
18 |
19 | Code
20 | map_int(1:3, ~ fail_at_3(.x, 2:1))
21 | Condition
22 | Error in `map_int()`:
23 | i In index: 3.
24 | Caused by error:
25 | ! Result must be length 1, not 2.
26 | Code
27 | map_int(1:3, ~ fail_at_3(.x, "x"))
28 | Condition
29 | Error in `map_int()`:
30 | i In index: 3.
31 | Caused by error:
32 | ! Can't coerce from a string to an integer.
33 | Code
34 | map(1:3, ~ fail_at_3(.x, stop("Doesn't work")))
35 | Condition
36 | Error in `map()`:
37 | i In index: 3.
38 | Caused by error in `fail_at_3()`:
39 | ! Doesn't work
40 |
41 | # error location uses name if present
42 |
43 | Code
44 | map_int(c(a = 1, b = 2, c = 3), ~ fail_at_3(.x, stop("Error")))
45 | Condition
46 | Error in `map_int()`:
47 | i In index: 3.
48 | i With name: c.
49 | Caused by error in `fail_at_3()`:
50 | ! Error
51 | Code
52 | map_int(c(a = 1, b = 2, 3), ~ fail_at_3(.x, stop("Error")))
53 | Condition
54 | Error in `map_int()`:
55 | i In index: 3.
56 | Caused by error in `fail_at_3()`:
57 | ! Error
58 |
59 | # requires output be length 1 and have common type
60 |
61 | Code
62 | map_vec(1:2, ~ rep(1, .x))
63 | Condition
64 | Error in `map_vec()`:
65 | ! `out[[2]]` must have size 1, not size 2.
66 | Code
67 | map_vec(1:2, ~ if (.x == 1) factor("x") else 1)
68 | Condition
69 | Error in `map_vec()`:
70 | ! Can't combine `[[1]]` > and `[[2]]` .
71 |
72 | # can enforce .ptype
73 |
74 | Code
75 | map_vec(1:2, ~ factor("x"), .ptype = integer())
76 | Condition
77 | Error in `map_vec()`:
78 | ! Can't convert `[[1]]` > to .
79 |
80 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/map2.md:
--------------------------------------------------------------------------------
1 | # verifies result types and length
2 |
3 | Code
4 | map2_int(1, 1, ~"x")
5 | Condition
6 | Error in `map2_int()`:
7 | i In index: 1.
8 | Caused by error:
9 | ! Can't coerce from a string to an integer.
10 | Code
11 | map2_int(1, 1, ~ 1:2)
12 | Condition
13 | Error in `map2_int()`:
14 | i In index: 1.
15 | Caused by error:
16 | ! Result must be length 1, not 2.
17 | Code
18 | map2_vec(1, 1, ~1, .ptype = character())
19 | Condition
20 | Error in `map2_vec()`:
21 | ! Can't convert `[[1]]` to .
22 |
23 | # requires vector inputs
24 |
25 | Code
26 | map2(environment(), "a", identity)
27 | Condition
28 | Error in `map2()`:
29 | ! `.x` must be a vector, not an environment.
30 | Code
31 | map2("a", environment(), "a", identity)
32 | Condition
33 | Error in `map2()`:
34 | ! `.y` must be a vector, not an environment.
35 |
36 | # recycles inputs
37 |
38 | Code
39 | map2(1:2, 1:3, `+`)
40 | Condition
41 | Error in `map2()`:
42 | ! Can't recycle `.x` (size 2) to match `.y` (size 3).
43 | Code
44 | map2(1:2, integer(), `+`)
45 | Condition
46 | Error in `map2()`:
47 | ! Can't recycle `.x` (size 2) to match `.y` (size 0).
48 |
49 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/modify-tree.md:
--------------------------------------------------------------------------------
1 | # validates inputs
2 |
3 | Code
4 | modify_tree(list(), is_node = ~1)
5 | Condition
6 | Error in `modify_tree()`:
7 | ! `is_node()` must return a single `TRUE` or `FALSE`, not a number.
8 | Code
9 | modify_tree(list(), is_node = 1)
10 | Condition
11 | Error in `modify_tree()`:
12 | ! Can't convert `is_node`, a double vector, to a function.
13 |
14 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/pluck-assign.md:
--------------------------------------------------------------------------------
1 | # assign_in() requires at least one location
2 |
3 | Code
4 | assign_in(x, NULL, value = "foo")
5 | Condition
6 | Error in `assign_in()`:
7 | ! `where` must contain at least one element.
8 |
9 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/pluck-depth.md:
--------------------------------------------------------------------------------
1 | # vec_depth() is deprecated
2 |
3 | Code
4 | . <- vec_depth(list())
5 | Condition
6 | Warning:
7 | `vec_depth()` was deprecated in purrr 1.0.0.
8 | i Please use `pluck_depth()` instead.
9 |
10 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/pmap.md:
--------------------------------------------------------------------------------
1 | # verifies result types and length
2 |
3 | Code
4 | pmap_int(list(1), ~"x")
5 | Condition
6 | Error in `pmap_int()`:
7 | i In index: 1.
8 | Caused by error:
9 | ! Can't coerce from a string to an integer.
10 | Code
11 | pmap_int(list(1), ~ 1:2)
12 | Condition
13 | Error in `pmap_int()`:
14 | i In index: 1.
15 | Caused by error:
16 | ! Result must be length 1, not 2.
17 | Code
18 | pmap_vec(list(1), ~1, .ptype = character())
19 | Condition
20 | Error in `pmap_vec()`:
21 | ! Can't convert `[[1]]` to .
22 |
23 | # requires list of vectors
24 |
25 | Code
26 | pmap(environment(), identity)
27 | Condition
28 | Error in `pmap()`:
29 | ! `.l` must be a list, not an environment.
30 | Code
31 | pmap(list(environment()), identity)
32 | Condition
33 | Error in `pmap()`:
34 | ! `.l[[1]]` must be a vector, not an environment.
35 |
36 | # recycles inputs
37 |
38 | Code
39 | pmap(list(1:2, 1:3), `+`)
40 | Condition
41 | Error in `pmap()`:
42 | ! Can't recycle `.l[[1]]` (size 2) to match `.l[[2]]` (size 3).
43 | Code
44 | pmap(list(1:2, integer()), `+`)
45 | Condition
46 | Error in `pmap()`:
47 | ! Can't recycle `.l[[1]]` (size 2) to match `.l[[2]]` (size 0).
48 |
49 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/rate.md:
--------------------------------------------------------------------------------
1 | # rates have print methods
2 |
3 | Code
4 | rate_delay(20, max_times = Inf)
5 | Message
6 |
7 | Attempts: 0/Inf
8 | pause: 20
9 | Code
10 | rate_backoff()
11 | Message
12 |
13 | Attempts: 0/3
14 | pause_base: 1
15 | pause_cap: 60
16 | pause_min: 1
17 |
18 | # rate_delay() delays
19 |
20 | Code
21 | rate_sleep(rate)
22 | Condition
23 | Error in `rate_sleep()`:
24 | ! Request failed after 3 attempts.
25 |
26 | ---
27 |
28 | Code
29 | rate_sleep(rate)
30 | Condition
31 | Error in `rate_sleep()`:
32 | ! This `rate` object has already be run more than `max_times` allows.
33 | i Do you need to reset it with `rate_reset()`?
34 |
35 | # rate_backoff() backs off
36 |
37 | Code
38 | rate_sleep(rate)
39 | Condition
40 | Error in `rate_sleep()`:
41 | ! Request failed after 3 attempts.
42 |
43 | ---
44 |
45 | Code
46 | rate_sleep(rate)
47 | Condition
48 | Error in `rate_sleep()`:
49 | ! This `rate` object has already be run more than `max_times` allows.
50 | i Do you need to reset it with `rate_reset()`?
51 |
52 | # rate_sleep() checks that rate is still valid
53 |
54 | Code
55 | rate_sleep(rate)
56 | Condition
57 | Error in `rate_sleep()`:
58 | ! Request failed after 0 attempts.
59 |
60 | ---
61 |
62 | Code
63 | rate_sleep(rate)
64 | Condition
65 | Error in `rate_sleep()`:
66 | ! This `rate` object has already be run more than `max_times` allows.
67 | i Do you need to reset it with `rate_reset()`?
68 |
69 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/reduce.md:
--------------------------------------------------------------------------------
1 | # empty input returns init or error
2 |
3 | Code
4 | reduce(list())
5 | Condition
6 | Error in `reduce()`:
7 | ! Must supply `.init` when `.x` is empty.
8 |
9 | # accumulate() does fail when simpification is required
10 |
11 | Code
12 | accumulate(list(1, "a"), ~.y, .simplify = TRUE)
13 | Condition
14 | Error in `accumulate()`:
15 | ! Can't combine `res[[1]]` and `res[[2]]` .
16 |
17 | # requires equal length vectors
18 |
19 | Code
20 | reduce2(1:3, 1, `+`)
21 | Condition
22 | Error in `reduce2()`:
23 | ! `.y` must have length 2, not 1.
24 |
25 | # requires init if `.x` is empty
26 |
27 | Code
28 | reduce2(list())
29 | Condition
30 | Error in `reduce2()`:
31 | ! Must supply `.init` when `.x` is empty.
32 |
33 | # right variants are retired
34 |
35 | Code
36 | . <- reduce_right(1:3, c)
37 | Condition
38 | Warning:
39 | `reduce_right()` was deprecated in purrr 0.3.0.
40 | i Please use the `.dir` argument of `reduce()` instead.
41 | Code
42 | . <- reduce2_right(1:3, 1:2, c)
43 | Condition
44 | Warning:
45 | `reduce2_right()` was deprecated in purrr 0.3.0.
46 | i Please use reverse your vectors and use `reduce2()` instead.
47 | Code
48 | . <- accumulate_right(1:3, c)
49 | Condition
50 | Warning:
51 | `accumulate_right()` was deprecated in purrr 0.3.0.
52 | i Please use the `.dir` argument of `accumulate()` instead.
53 |
54 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/superseded-flatten.md:
--------------------------------------------------------------------------------
1 | # input must be a list
2 |
3 | Code
4 | flatten(1)
5 | Condition
6 | Error in `flatten()`:
7 | ! `.x` must be a list, not a number.
8 |
9 | ---
10 |
11 | Code
12 | flatten_dbl(1)
13 | Condition
14 | Error in `flatten_dbl()`:
15 | ! `.x` must be a list, not a number.
16 |
17 | # contents of list must be supported types
18 |
19 | Code
20 | flatten(list(quote(a)))
21 | Condition
22 | Error in `flatten()`:
23 | ! `.x[[1]]` must be a vector, not a symbol.
24 |
25 | ---
26 |
27 | Code
28 | flatten(list(expression(a)))
29 | Condition
30 | Error in `flatten()`:
31 | ! `.x[[1]]` must be a vector, not an expression vector.
32 |
33 | # must be a list
34 |
35 | Code
36 | flatten_lgl(1)
37 | Condition
38 | Error in `flatten_lgl()`:
39 | ! `.x` must be a list, not a number.
40 |
41 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/superseded-transpose.md:
--------------------------------------------------------------------------------
1 | # input must be a list
2 |
3 | Code
4 | transpose(1:3)
5 | Condition
6 | Error in `transpose()`:
7 | ! `.l` must be a list, not an integer vector.
8 |
9 | # elements of input must be atomic vectors
10 |
11 | Code
12 | transpose(list(environment()))
13 | Condition
14 | Error in `transpose()`:
15 | ! Element 1 must be a vector, not an environment.
16 |
17 | ---
18 |
19 | Code
20 | transpose(list(list(), environment()))
21 | Condition
22 | Error in `transpose()`:
23 | ! Element 2 must be a vector, not an environment.
24 |
25 | # can't transpose expressions
26 |
27 | Code
28 | transpose(list(expression(a)))
29 | Condition
30 | Error in `transpose()`:
31 | ! Transposed element must be a vector, not an expression vector.
32 |
33 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/utils.md:
--------------------------------------------------------------------------------
1 | # errors on invalid subsetting vectors
2 |
3 | Code
4 | where_at(x, c(FALSE, TRUE))
5 | Condition
6 | Error:
7 | ! Can't subset elements with `at`.
8 | x Logical subscript `at` must be size 1 or 3, not 2.
9 | Code
10 | where_at(x, NA_real_)
11 | Condition
12 | Error:
13 | ! Can't subset elements.
14 | x Subscript can't contain missing values.
15 | x It has a missing value at location 1.
16 | Code
17 | where_at(x, 4)
18 | Condition
19 | Error:
20 | ! Can't subset elements past the end.
21 | i Location 4 doesn't exist.
22 | i There are only 3 elements.
23 |
24 | # validates its inputs
25 |
26 | Code
27 | where_at(x, list())
28 | Condition
29 | Error:
30 | ! `list()` must be a numeric vector, character vector, or function, not an empty list.
31 |
32 | # tidyselect `at` is deprecated
33 |
34 | Code
35 | . <- where_at(data.frame(x = 1), vars("x"), user_env = globalenv())
36 | Condition
37 | Warning:
38 | Using `vars()` in .at was deprecated in purrr 1.0.0.
39 |
40 | # pairlists, expressions, and calls are deprecated
41 |
42 | Code
43 | x <- vctrs_vec_compat(expression(1, 2), globalenv())
44 | Condition
45 | Warning:
46 | Use of calls and pairlists in map functions was deprecated in purrr 1.0.0.
47 | i Please coerce explicitly with `as.list()`
48 |
49 | ---
50 |
51 | Code
52 | x <- vctrs_vec_compat(pairlist(1, 2), globalenv())
53 | Condition
54 | Warning:
55 | Use of pairlists in map functions was deprecated in purrr 1.0.0.
56 | i Please coerce explicitly with `as.list()`
57 |
58 | ---
59 |
60 | Code
61 | x <- vctrs_vec_compat(quote(f(a, b = 1)), globalenv())
62 | Condition
63 | Warning:
64 | Use of calls and pairlists in map functions was deprecated in purrr 1.0.0.
65 | i Please coerce explicitly with `as.list()`
66 |
67 | # can't work with regular S4 objects
68 |
69 | Code
70 | map(foo(), identity)
71 | Condition
72 | Error in `x[[i]]`:
73 | ! this S4 class is not subsettable
74 |
75 |
--------------------------------------------------------------------------------
/tests/testthat/helper-map.R:
--------------------------------------------------------------------------------
1 | named <- function(x) set_names(x, chr())
2 |
3 | # Until we can reexport from rlang
4 | vars <- function(...) rlang::quos(...)
5 |
--------------------------------------------------------------------------------
/tests/testthat/helper.R:
--------------------------------------------------------------------------------
1 | expect_bare <- function(x, type) {
2 | predicate <- switch(
3 | type,
4 | logical = is_bare_logical,
5 | integer = is_bare_integer,
6 | double = is_bare_double,
7 | complex = is_bare_complex,
8 | character = is_bare_character,
9 | raw = is_bare_raw,
10 | list = is_bare_list,
11 | )
12 |
13 | expect_true(predicate(x))
14 | }
15 |
16 | local_name_repair_quiet <- function(frame = caller_env()) {
17 | local_options(rlib_name_repair_verbosity = "quiet", .frame = frame)
18 | }
19 | local_name_repair_verbose <- function(frame = caller_env()) {
20 | local_options(rlib_name_repair_verbosity = "verbose", .frame = frame)
21 | }
22 |
23 | local_methods <- function(..., .frame = caller_env()) {
24 | local_bindings(..., .env = global_env(), .frame = .frame)
25 | }
26 |
--------------------------------------------------------------------------------
/tests/testthat/setup.R:
--------------------------------------------------------------------------------
1 | Sys.setlocale("LC_MESSAGES", "C")
2 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-auto-browse.R:
--------------------------------------------------------------------------------
1 | test_that("auto_browse() not intended for primitive functions", {
2 | expect_snapshot(auto_browse(log)(NULL), error = TRUE)
3 | expect_no_error(auto_browse(identity)(NULL))
4 | })
5 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-insistently.R:
--------------------------------------------------------------------------------
1 | test_that("insistently() resets rate state", {
2 | fn <- insistently(compose(), rate_delay(1, max_times = 0))
3 | expect_snapshot_error(fn(), class = "purrr_error_rate_excess")
4 | expect_snapshot_error(fn(), class = "purrr_error_rate_excess")
5 | })
6 |
7 | test_that("validates inputs", {
8 | expect_snapshot(error = TRUE, {
9 | insistently(mean, 10)
10 | })
11 | })
12 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-negate.R:
--------------------------------------------------------------------------------
1 | test_that("negate works with both functions and vectors", {
2 | true <- function(...) TRUE
3 | expect_equal(negate(true)(), FALSE)
4 | expect_equal(negate("x")(list(x = TRUE)), FALSE)
5 |
6 | expect_equal(negate(is.null)(TRUE), TRUE)
7 | expect_equal(negate(is.null)(NULL), FALSE)
8 | })
9 |
10 | test_that("negate() works with early returns", {
11 | expect_false(negate(~ return(TRUE))())
12 | })
13 |
14 | test_that("negate() works with generic functions and local methods", {
15 | is_foobar <- function(x) UseMethod("is_foobar")
16 | local({
17 | is_foobar.default <- function(x) TRUE
18 | expect_false(negate(is_foobar)())
19 | })
20 | })
21 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-possibly.R:
--------------------------------------------------------------------------------
1 | test_that("possibly returns default value on failure", {
2 | expect_identical(possibly(log, NA_real_)("a"), NA_real_)
3 | })
4 |
5 | test_that("possibly emits a message on failure if quiet = FALSE", {
6 | f <- function(...) stop("tilt")
7 | expect_message({
8 | possibly(f, NA_real_, quiet = FALSE)()
9 | }, regexp = "tilt")
10 | })
11 |
12 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-quietly.R:
--------------------------------------------------------------------------------
1 | test_that("quietly captures output", {
2 | f <- function() {
3 | cat(1)
4 | message(2, appendLF = FALSE)
5 | warning(3)
6 | 4
7 | }
8 | expect_output(quietly(f)(), NA)
9 | expect_message(quietly(f)(), NA)
10 | expect_warning(quietly(f)(), NA)
11 |
12 | out <- quietly(f)()
13 | expect_equal(out, list(
14 | result = 4,
15 | output = "1",
16 | warnings = "3",
17 | messages = "2"
18 | ))
19 | })
20 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-safely.R:
--------------------------------------------------------------------------------
1 | test_that("safely has NULL error when successful", {
2 | out <- safely(log10)(10)
3 | expect_equal(out, list(result = 1, error = NULL))
4 | })
5 |
6 | test_that("safely has NULL result on failure", {
7 | out <- safely(log10)("a")
8 | expect_equal(out$result, NULL)
9 | expect_equal(out$error$message,
10 | "non-numeric argument to mathematical function")
11 | })
12 |
13 |
--------------------------------------------------------------------------------
/tests/testthat/test-adverb-slowly.R:
--------------------------------------------------------------------------------
1 | test_that("validates inputs", {
2 | expect_snapshot(error = TRUE, {
3 | slowly(mean, 10)
4 | })
5 | })
6 |
--------------------------------------------------------------------------------
/tests/testthat/test-arrays.R:
--------------------------------------------------------------------------------
1 | x <- array(1:12, c(2, 2, 3), dimnames = list(letters[1:2], LETTERS[1:2], NULL))
2 |
3 | test_that("array_branch creates a flat list when no margin specified", {
4 | expect_length(array_branch(x), 12)
5 | })
6 |
7 | test_that("array_branch wraps array in list when margin has length 0", {
8 | expect_identical(array_branch(x, numeric(0)), list(x))
9 | })
10 |
11 | test_that("array_branch works on vectors", {
12 | expect_identical(array_branch(1:3), list(1L, 2L, 3L))
13 | expect_identical(array_branch(1:3, 1), list(1L, 2L, 3L))
14 | })
15 |
16 | test_that("array_branch throws an error for wrong margins on a vector", {
17 | expect_snapshot(array_branch(1:3, 2), error = TRUE)
18 | })
19 |
20 | test_that("length depends on whether list is flattened or not", {
21 | m1 <- c(3, 1)
22 | m2 <- 3
23 | expect_length(array_branch(x, m1), prod(dim(x)[m1]))
24 | expect_length(array_tree(x, m1), prod(dim(x)[m2]))
25 | })
26 |
27 | test_that("array_branch retains dimnames when going over one dimension", {
28 | expect_identical(names(array_branch(x, 1)), letters[1:2])
29 | expect_identical(names(array_branch(x, 2)), LETTERS[1:2])
30 | expect_identical(names(array_branch(x, 2:3)[[1]]), letters[1:2])
31 | })
32 |
--------------------------------------------------------------------------------
/tests/testthat/test-coerce.R:
--------------------------------------------------------------------------------
1 | test_that("can coerce to logical vectors",{
2 | expect_equal(coerce_lgl(c(TRUE, FALSE, NA)), c(TRUE, FALSE, NA))
3 |
4 | expect_equal(coerce_lgl(c(1L, 0L, NA)), c(TRUE, FALSE, NA))
5 | expect_snapshot(coerce_lgl(2L), error = TRUE)
6 |
7 | expect_equal(coerce_lgl(c(1, 0, NA)), c(TRUE, FALSE, NA))
8 | expect_snapshot(coerce_lgl(1.5), error = TRUE)
9 |
10 | expect_snapshot(coerce_lgl("true"), error = TRUE)
11 | })
12 |
13 | test_that("can coerce to integer vectors", {
14 | expect_identical(coerce_int(c(TRUE, FALSE, NA)), c(1L, 0L, NA))
15 |
16 | expect_identical(coerce_int(c(NA, 1L, 10L)), c(NA, 1L, 10L))
17 |
18 | expect_identical(coerce_int(c(NA, 1, 10)), c(NA, 1L, 10L))
19 | expect_snapshot(coerce_int(1.5), error = TRUE)
20 |
21 | expect_snapshot(coerce_int("1"), error = TRUE)
22 | })
23 |
24 | test_that("can coerce to double vctrs", {
25 | expect_identical(coerce_dbl(c(TRUE, FALSE, NA)), c(1, 0, NA))
26 |
27 | expect_identical(coerce_dbl(c(NA, 1L, 10L)), c(NA, 1, 10))
28 |
29 | expect_identical(coerce_dbl(c(NA, 1.5)), c(NA, 1.5))
30 |
31 | expect_snapshot(coerce_dbl("1.5"), error = TRUE)
32 | })
33 |
34 | test_that("can coerce to character vectors", {
35 | expect_equal(coerce_chr(NA), NA_character_)
36 |
37 | expect_snapshot({
38 | expect_equal(coerce_chr(TRUE), "TRUE")
39 | expect_equal(coerce_chr(1L), "1")
40 | expect_equal(coerce_chr(1.5), "1.500000")
41 | })
42 |
43 | expect_equal(coerce_chr("x"), "x")
44 | })
45 |
46 | test_that("error captures correct env", {
47 | indirect <- function() {
48 | purrr::map_chr(1:4, identity)
49 | }
50 | environment(indirect) <- ns_env("rlang")
51 |
52 | expect_snapshot({
53 | map_chr(1:4, identity)
54 | indirect()
55 | })
56 |
57 | })
58 |
59 | test_that("warns once per vector", {
60 | expect_warning(expect_warning(coerce_chr(1:5)), NA)
61 | })
62 |
63 | test_that("can't coerce to expressions", {
64 | expect_snapshot(coerce(list(1), "expression"), error = TRUE)
65 | })
66 |
--------------------------------------------------------------------------------
/tests/testthat/test-conditions.R:
--------------------------------------------------------------------------------
1 | test_that("stop_bad_type() constructs default `what`", {
2 | expect_snapshot(stop_bad_type(NA, "`NULL`"), error = TRUE)
3 | expect_snapshot(stop_bad_type(NA, "`NULL`", arg = ".foo"), error = TRUE)
4 | expect_snapshot(stop_bad_type(NA, "`NULL`", arg = quote(.foo)), error = TRUE)
5 | })
6 |
7 | test_that("stop_bad_element_type() constructs type errors", {
8 | expect_snapshot(stop_bad_element_type(1:3, 3, "a foobaz"), error = TRUE)
9 | expect_snapshot(stop_bad_element_type(1:3, 3, "a foobaz", actual = "a quux"), error = TRUE)
10 | expect_snapshot(stop_bad_element_type(1:3, 3, "a foobaz", arg = "..arg"), error = TRUE)
11 | })
12 |
13 | test_that("stop_bad_element_type() accepts `what`", {
14 | expect_snapshot(stop_bad_element_type(1:3, 3, "a foobaz", what = "Result"), error = TRUE)
15 | })
16 |
17 | test_that("stop_bad_element_length() constructs error message", {
18 | expect_snapshot(stop_bad_element_length(1:3, 8, 10), error = TRUE)
19 | expect_snapshot(stop_bad_element_length(1:3, 8, 10, arg = ".foo"), error = TRUE)
20 | expect_snapshot(stop_bad_element_length(1:3, 8, 10, arg = ".foo", what = "Result"), error = TRUE)
21 | expect_snapshot(stop_bad_element_length(1:3, 8, 10, arg = ".foo", what = "Result", recycle = TRUE), error = TRUE)
22 | })
23 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-along.R:
--------------------------------------------------------------------------------
1 | test_that("list-along is deprecated", {
2 | expect_snapshot({
3 | . <- list_along(1:4)
4 | })
5 | })
6 |
7 | test_that("list_along works", {
8 | local_options(lifecycle_verbosity = "quiet")
9 |
10 | x <- 1:5
11 | expect_identical(list_along(x), vector("list", 5))
12 | })
13 |
14 | test_that("rep_along works", {
15 | local_options(lifecycle_verbosity = "quiet")
16 |
17 | expect_equal(
18 | rep_along(c("c", "b", "a"), 1:3),
19 | rep_along(c("d", "f", "e"), 1:3)
20 | )
21 | })
22 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-cross.R:
--------------------------------------------------------------------------------
1 | test_that("long format corresponds to expand.grid output", {
2 | skip_if_not_installed("tibble")
3 | local_options(lifecycle_verbosity = "quiet")
4 |
5 | x <- list(a = 1:3, b = 4:9)
6 |
7 | out1 <- cross_df(x)
8 | out2 <- expand.grid(x, KEEP.OUT.ATTRS = FALSE) %>% tibble::as_tibble()
9 |
10 | expect_equal(out1, out2)
11 | })
12 |
13 | test_that("filtering works", {
14 | local_options(lifecycle_verbosity = "quiet")
15 | filter <- function(x, y) x >= y
16 | out <- cross2(1:3, 1:3, .filter = filter)
17 | expect_equal(out, list(list(1, 2), list(1, 3), list(2, 3)))
18 | })
19 |
20 | test_that("filtering requires a predicate function", {
21 | local_options(lifecycle_verbosity = "quiet")
22 | expect_snapshot(cross2(1:3, 1:3, .filter = ~ c(TRUE, TRUE)), error = TRUE)
23 | })
24 |
25 | test_that("filtering fails when filter function doesn't return a logical", {
26 | local_options(lifecycle_verbosity = "quiet")
27 | filter <- function(x, y, z) x + y + z
28 | expect_snapshot(cross3(1:3, 1:3, 1:3, .filter = filter), error = TRUE)
29 | })
30 |
31 | test_that("works with empty input", {
32 | local_options(lifecycle_verbosity = "quiet")
33 | expect_equal(cross(list()), list())
34 | expect_equal(cross(NULL), NULL)
35 | })
36 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-lift.R:
--------------------------------------------------------------------------------
1 | test_that("lift_dl and lift_ld are inverses of each other", {
2 | options(lifecycle_verbosity = "quiet")
3 |
4 | expect_identical(
5 | sum %>%
6 | lift_dl(.unnamed = TRUE) %>%
7 | do.call(list(3, NA, 4, na.rm = TRUE)),
8 | sum %>%
9 | lift_dl() %>%
10 | lift_ld() %>%
11 | exec(3, NA, 4, na.rm = TRUE)
12 | )
13 | })
14 |
15 | test_that("lift_dv is from ... to c(...)", {
16 | options(lifecycle_verbosity = "quiet")
17 |
18 | expect_equal(lift_dv(range, .unnamed = TRUE)(1:10), c(1, 10))
19 | })
20 |
21 | test_that("lift_vd is from c(...) to ...", {
22 | options(lifecycle_verbosity = "quiet")
23 |
24 | expect_equal(lift_vd(mean)(1, 2), 1.5)
25 | })
26 |
27 | test_that("lift_vl is from c(...) to list(...)", {
28 | options(lifecycle_verbosity = "quiet")
29 |
30 | expect_equal(lift_vl(mean)(list(1, 2)), 1.5)
31 | })
32 |
33 | test_that("lift_lv is from list(...) to c(...)", {
34 | options(lifecycle_verbosity = "quiet")
35 |
36 | glue <- function(l) {
37 | if (!is.list(l)) stop("not a list")
38 | l %>% do.call(paste, .)
39 | }
40 | expect_identical(lift_lv(glue)(letters), paste(letters, collapse = " "))
41 | })
42 |
43 |
44 | test_that("lift functions are deprecated", {
45 | expect_snapshot({
46 | . <- lift_dl(function() {})
47 | . <- lift_dv(function() {})
48 | . <- lift_vl(function() {})
49 | . <- lift_vd(function() {})
50 | . <- lift_ld(function() {})
51 | . <- lift_lv(function() {})
52 | })
53 |
54 | })
55 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-map.R:
--------------------------------------------------------------------------------
1 | test_that("at_depth is defunct", {
2 | expect_snapshot(at_depth(), error = TRUE)
3 | })
4 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-prepend.R:
--------------------------------------------------------------------------------
1 | test_that("prepend is deprecated", {
2 | expect_snapshot({
3 | . <- prepend(1, 2)
4 | })
5 | })
6 |
7 | test_that("prepend is clearer version of merging with c()", {
8 | local_options(lifecycle_verbosity = "quiet")
9 |
10 | x <- 1:3
11 | expect_identical(
12 | x %>% prepend(4),
13 | x %>% c(4, .)
14 | )
15 | expect_identical(
16 | x %>% prepend(4, before = 3),
17 | x %>% {
18 | c(.[1:2], 4, .[3])
19 | }
20 | )
21 | })
22 |
23 | test_that("prepend appends at the beginning for empty list by default", {
24 | local_options(lifecycle_verbosity = "quiet")
25 |
26 | x <- list()
27 | expect_identical(
28 | x %>% prepend(1),
29 | x %>% c(1, .)
30 | )
31 | })
32 |
33 | test_that("prepend throws error if before param is neither NULL nor between 1 and length(x)", {
34 | local_options(lifecycle_verbosity = "quiet")
35 |
36 | expect_snapshot(prepend(list(), 1, before = 1), error = TRUE)
37 | x <- as.list(1:3)
38 | expect_snapshot(x %>% prepend(4, before = 0), error = TRUE)
39 | expect_snapshot(x %>% prepend(4, before = 4), error = TRUE)
40 | })
41 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-rerun.R:
--------------------------------------------------------------------------------
1 | test_that("is deprecated", {
2 | expect_snapshot({
3 | . <- rerun(5, rnorm(1))
4 | . <- rerun(5, rnorm(1), rnorm(2))
5 | })
6 |
7 | })
8 |
9 | test_that("single unnamed arg doesn't get extra list", {
10 | local_options(lifecycle_verbosity = "quiet")
11 | expect_equal(rerun(2, 1), list(1, 1))
12 | })
13 |
14 | test_that("single named arg gets extra list", {
15 | local_options(lifecycle_verbosity = "quiet")
16 | expect_equal(rerun(2, a = 1), list(list(a = 1), list(a = 1)))
17 | })
18 |
19 | test_that("every run is different", {
20 | local_options(lifecycle_verbosity = "quiet")
21 | x <- rerun(2, runif(1))
22 | expect_true(x[[1]] != x[[2]])
23 | })
24 |
25 | test_that("rerun uses scope of expression", {
26 | local_options(lifecycle_verbosity = "quiet")
27 | f <- function(n) {
28 | rerun(1, x = seq_len(n))
29 | }
30 |
31 | expect_equal(f(10)[[1]]$x, 1:10)
32 | })
33 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-splice.R:
--------------------------------------------------------------------------------
1 | test_that("predicate controls which elements get spliced", {
2 | x <- list(1, 2, list(3, 4))
3 |
4 | expect_equal(splice_if(x, ~ FALSE), x)
5 | expect_equal(splice_if(x, is.list), list(1, 2, 3, 4))
6 | })
7 |
8 | test_that("splice() produces correctly named lists", {
9 | local_options(lifecycle_verbosity = "quiet")
10 | inputs <- list(arg1 = "a", arg2 = "b")
11 |
12 | out1 <- splice(inputs, arg3 = c("c1", "c2"))
13 | expect_named(out1, c("arg1", "arg2", "arg3"))
14 |
15 | out2 <- splice(inputs, arg = list(arg3 = 1, arg4 = 2))
16 | expect_named(out2, c("arg1", "arg2", "arg3", "arg4"))
17 | })
18 |
19 | test_that("splice is deprecated", {
20 | expect_snapshot({
21 | . <- splice()
22 | })
23 |
24 | })
25 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-utils.R:
--------------------------------------------------------------------------------
1 | test_that("rdunif and rbernoulli are deprecated", {
2 | expect_snapshot({
3 | . <- rdunif(10, 1)
4 | . <- rbernoulli(10)
5 | })
6 | })
7 |
8 | test_that("rbernoulli is a special case of rbinom", {
9 | local_options(lifecycle_verbosity = "quiet")
10 |
11 | set.seed(1)
12 | x <- rbernoulli(10)
13 |
14 | set.seed(1)
15 | y <- ifelse(rbinom(10, 1, 0.5) == 1, TRUE, FALSE)
16 |
17 | expect_equal(x, y)
18 | })
19 |
20 | test_that("rdunif works", {
21 | local_options(lifecycle_verbosity = "quiet")
22 |
23 | expect_length(rdunif(100, 10), 100)
24 | })
25 |
26 | test_that("rdunif fails if a and b are not unit length numbers", {
27 | local_options(lifecycle_verbosity = "quiet")
28 |
29 | expect_snapshot(rdunif(1000, 1, "a"), error = TRUE)
30 | expect_snapshot(rdunif(1000, 1, c(0.5, 0.2)), error = TRUE)
31 | expect_snapshot(rdunif(1000, FALSE, 2), error = TRUE)
32 | expect_snapshot(rdunif(1000, c(2, 3), 2), error = TRUE)
33 | })
34 |
35 |
36 | # Lifecycle ---------------------------------------------------------------
37 |
38 | test_that("%@% is an infix attribute accessor", {
39 | local_options(lifecycle_verbosity = "quiet")
40 | expect_identical(mtcars %@% "names", attr(mtcars, "names"))
41 | })
42 |
43 |
--------------------------------------------------------------------------------
/tests/testthat/test-deprec-when.R:
--------------------------------------------------------------------------------
1 | test_that("when is deprecated", {
2 | expect_snapshot({
3 | . <- when(1:5 < 3 ~ 1, ~ 0)
4 | })
5 | })
6 |
7 | test_that("when chooses the correct action", {
8 | local_options(lifecycle_verbosity = "quiet")
9 |
10 | x <-
11 | 1:5 %>%
12 | when(
13 | sum(.) <= 50 ~ sum(.),
14 | sum(.) <= 100 ~ sum(.) / 2,
15 | ~ 0
16 | )
17 |
18 | expect_equal(x, 15)
19 |
20 | y <-
21 | 1:10 %>%
22 | when(
23 | sum(.) <= 50 ~ sum(.),
24 | sum(.) <= 100 ~ sum(.) / 2,
25 | ~ 0
26 | )
27 |
28 | expect_equal(y, sum(1:10) / 2)
29 |
30 | z <-
31 | 1:100 %>%
32 | when(
33 | sum(.) <= 50 ~ sum(.),
34 | sum(.) <= 100 ~ sum(.) / 2,
35 | ~ 0
36 | )
37 |
38 | expect_equal(z, 0)
39 | })
40 |
41 | test_that("named arguments work with when", {
42 | local_options(lifecycle_verbosity = "quiet")
43 |
44 | x <-
45 | 1:10 %>%
46 | when(
47 | sum(.) <= x ~ sum(.) * x,
48 | sum(.) <= 2 * x ~ sum(.) * x / 2,
49 | ~ 0,
50 | x = 60
51 | )
52 |
53 | expect_equal(x, sum(1:10) * 60)
54 | })
55 |
56 | test_that("default values work without a formula", {
57 | local_options(lifecycle_verbosity = "quiet")
58 |
59 | x <- iris %>%
60 | subset(Sepal.Length > 10) %>%
61 | when(
62 | nrow(.) > 0 ~ .,
63 | head(iris, 10)
64 | )
65 |
66 | expect_equal(x, head(iris, 10))
67 | })
68 |
69 | test_that("error when named arguments have no matching conditions", {
70 | local_options(lifecycle_verbosity = "quiet")
71 |
72 | expect_snapshot(1:5 %>% when(a = sum(.) < 5 ~ 3), error = TRUE)
73 | })
74 |
--------------------------------------------------------------------------------
/tests/testthat/test-detect.R:
--------------------------------------------------------------------------------
1 | y <- 4:10
2 |
3 | test_that("detect functions work", {
4 | is_odd <- function(x) x %% 2 == 1
5 | expect_equal(detect(y, is_odd), 5)
6 | expect_equal(detect_index(y, is_odd), 2)
7 | expect_equal(detect(y, is_odd, .dir = "backward"), 9)
8 | expect_equal(detect_index(y, is_odd, .dir = "backward"), 6)
9 | })
10 |
11 | test_that("detect returns NULL when match not found", {
12 | expect_null(detect(y, function(x) x > 11))
13 | })
14 |
15 | test_that("detect_index returns 0 when match not found", {
16 | expect_equal(detect_index(y, function(x) x > 11), 0)
17 | })
18 |
19 | test_that("has_element checks whether a list contains an object", {
20 | expect_true(has_element(list(1, 2), 1))
21 | expect_false(has_element(list(1, 2), 3))
22 | })
23 |
24 | test_that("`detect()` requires a predicate function", {
25 | expect_snapshot(detect(list(1:2, 2), is.na), error = TRUE)
26 | expect_snapshot(detect_index(list(1:2, 2), is.na), error = TRUE)
27 | })
28 |
29 |
30 | # Lifecycle ---------------------------------------------------------------
31 |
32 | test_that("`.right` argument is retired", {
33 |
34 | expect_snapshot({
35 | . <- detect(1:2, ~ TRUE, .right = TRUE)
36 | . <- detect_index(1:2, ~ TRUE, .right = TRUE)
37 | })
38 | })
39 |
40 | test_that("`.right` argument still works", {
41 | local_options(lifecycle_verbosity = "quiet")
42 | is_odd <- function(x) x %% 2 == 1
43 | expect_equal(detect(y, is_odd, .right = TRUE), 9)
44 | expect_equal(detect_index(y, is_odd, .right = TRUE), 6)
45 | })
46 |
--------------------------------------------------------------------------------
/tests/testthat/test-every-some-none.R:
--------------------------------------------------------------------------------
1 | test_that("every returns TRUE if all elements are TRUE", {
2 | x <- list(0, 1, TRUE)
3 | expect_false(every(x, isTRUE))
4 | expect_true(every(x[3], isTRUE))
5 | })
6 |
7 | test_that("some returns FALSE if all elements are FALSE", {
8 | x <- list(1, 0, FALSE)
9 | expect_false(some(x, isTRUE))
10 | expect_true(some(x[1], negate(isTRUE)))
11 | })
12 |
13 | test_that("none returns TRUE if all elements are FALSE", {
14 | x <- list(1, 0, TRUE)
15 | expect_false(none(x, isTRUE))
16 | expect_true(none(x[1], isTRUE))
17 | })
18 |
19 | test_that("every() requires logical value", {
20 | expect_snapshot(every(list(1:3), identity), error = TRUE)
21 | expect_snapshot(every(list(function() NULL), identity), error = TRUE)
22 | })
23 |
24 | test_that("every() has the same behaviour as `&&` (#751)", {
25 | expect_false(every(list(NA, FALSE), identity))
26 | expect_false(every(list(FALSE, NA), identity))
27 |
28 | expect_identical(every(list(NA, TRUE), identity), NA)
29 | expect_identical(every(list(TRUE, NA), identity), NA)
30 | expect_identical(every(list(NA, NA), identity), NA)
31 | })
32 |
33 | test_that("some() has the same behaviour as `||`", {
34 | expect_true(some(list(TRUE, NA), identity))
35 | expect_true(some(list(NA, TRUE), identity))
36 |
37 | expect_identical(some(list(NA, FALSE), identity), NA)
38 | expect_identical(some(list(FALSE, NA), identity), NA)
39 | expect_identical(some(list(NA, NA), identity), NA)
40 | })
41 |
--------------------------------------------------------------------------------
/tests/testthat/test-head-tail.R:
--------------------------------------------------------------------------------
1 | y <- 1:100
2 |
3 | test_that("head_while works", {
4 | expect_length(head_while(y, function(x) x <= 15), 15)
5 | })
6 |
7 | test_that("tail_while works", {
8 | expect_length(tail_while(y, function(x) x >= 86), 15)
9 | })
10 |
11 | test_that("original vector returned if predicate satisfied by all elements", {
12 | expect_identical(head_while(y, function(x) x <= 100), y)
13 | expect_identical(tail_while(y, function(x) x >= 0), y)
14 | })
15 |
16 | test_that("head_while and tail_while require predicate function", {
17 | expect_snapshot(head_while(1:3, ~ NA), error = TRUE)
18 | expect_snapshot(tail_while(1:3, ~ c(TRUE, FALSE)), error = TRUE)
19 | })
20 |
--------------------------------------------------------------------------------
/tests/testthat/test-imap.R:
--------------------------------------------------------------------------------
1 | x <- 1:3 %>% set_names()
2 |
3 | test_that("imap is special case of map2", {
4 | expect_identical(imap(x, paste), map2(x, names(x), paste))
5 | })
6 |
7 | test_that("imap always returns a list", {
8 | expect_bare(imap(x, paste), "list")
9 | })
10 |
11 | test_that("atomic vector imap works", {
12 | expect_true(all(imap_lgl(x, `==`)))
13 | expect_length(imap_chr(x, paste), 3)
14 | expect_equal(imap_int(x, ~ .x + as.integer(.y)), x * 2)
15 | expect_equal(imap_dbl(x, ~ .x + as.numeric(.y)), x * 2)
16 | expect_equal(imap_vec(x, ~ .x + as.numeric(.y)), x * 2)
17 | })
18 |
19 | test_that("iwalk returns invisibly", {
20 | expect_output(iwalk(mtcars, ~ cat(.y, ": ", median(.x), "\n", sep = "")))
21 | })
22 |
--------------------------------------------------------------------------------
/tests/testthat/test-keep.R:
--------------------------------------------------------------------------------
1 | test_that("can keep/discard with logical vector", {
2 | expect_equal(keep(1:3, c(TRUE, FALSE, TRUE)), c(1, 3))
3 | expect_equal(discard(1:3, c(TRUE, FALSE, TRUE)), 2)
4 | })
5 |
6 | test_that("can keep/discard with predicate", {
7 | expect_equal(keep(1:3, ~ .x != 2), c(1, 3))
8 | expect_equal(discard(1:3, ~ .x != 2), c(2))
9 | })
10 |
11 | test_that("keep() and discard() require predicate functions", {
12 | expect_snapshot(error = TRUE, {
13 | keep(1:3, ~ NA)
14 | discard(1:3, ~ NA)
15 | })
16 | })
17 |
18 | # keep_at / discard_at ----------------------------------------------------
19 |
20 | test_that("can keep_at/discard_at with character vector", {
21 | x <- list(a = 1, b = 1, c = 1)
22 | expect_equal(keep_at(x, "b"), list(b = 1))
23 | expect_equal(discard_at(x, "b"), list(a = 1, c = 1))
24 | })
25 |
26 | test_that("can keep_at/discard_at with function", {
27 | x <- list(a = 1, b = 1, c = 1)
28 | expect_equal(keep_at(x, ~ . == "b"), list(b = 1))
29 | expect_equal(discard_at(x, ~ . == "b"), list(a = 1, c = 1))
30 | })
31 |
32 | test_that("discard_at works when nothing discarded", {
33 | x <- list(a = 1, b = 1, c = 1)
34 | expect_equal(discard_at(x, "d"), x)
35 | })
36 |
--------------------------------------------------------------------------------
/tests/testthat/test-list-flatten.R:
--------------------------------------------------------------------------------
1 | test_that("flattening removes single layer of nesting", {
2 | expect_equal(list_flatten(list(list(1), list(2))), list(1, 2))
3 | expect_equal(list_flatten(list(list(1), list(list(2)))), list(1, list(2)))
4 | expect_equal(list_flatten(list(list(1), list(), list(2))), list(1, 2))
5 | })
6 |
7 | test_that("flattening a flat list is idempotent", {
8 | expect_equal(list_flatten(list(1, 2)), list(1, 2))
9 | })
10 |
11 | test_that("uses either inner or outer names if only one present", {
12 | expect_equal(list_flatten(list(x = list(1), list(y = 2))), list(x = 1, y = 2))
13 | })
14 |
15 | test_that("can control names if both present", {
16 | x <- list(a = list(x = 1))
17 | expect_equal(list_flatten(x), list(a_x = 1))
18 | expect_equal(list_flatten(x, name_spec = "{inner}"), list(x = 1))
19 | expect_equal(list_flatten(x, name_spec = "{outer}"), list(a = 1))
20 | })
21 |
22 | test_that("requires a list", {
23 | expect_snapshot(list_flatten(1:2), error = TRUE)
24 | })
25 |
26 | test_that("list_flatten() restores", {
27 | # This simulates a recursive list-of type
28 | my_num_list <- function(...) {
29 | new_my_num_list(list2(...))
30 | }
31 | new_my_num_list <- function(xs) {
32 | stopifnot(
33 | every(xs, function(x) {
34 | is_null(x) || is.numeric(x) || inherits(x, "my_num_list")
35 | })
36 | )
37 | new_vctr(xs, class = "my_num_list")
38 | }
39 |
40 | local_methods(
41 | vec_restore.my_num_list = function(x, to, ...) {
42 | new_my_num_list(x)
43 | }
44 | )
45 |
46 | xs <- my_num_list(1, 2, my_num_list(3:4))
47 | expect_equal(
48 | list_flatten(xs),
49 | my_num_list(1, 2, 3:4)
50 | )
51 | })
52 |
53 | test_that("list_flatten() supports strict types", {
54 | local_methods(
55 | vec_cast.list.my_strict_list = function(x, to, ...) {
56 | abort("Can't coerce to list.")
57 | }
58 | )
59 |
60 | x <- structure(list(1), class = c("my_strict_list", "list"))
61 |
62 | expect_equal(
63 | list_flatten(list(x)),
64 | list(1)
65 | )
66 | })
67 |
68 | test_that("list_flatten() works with vctrs::list_of()", {
69 | # Currently only with flat lists because list_of can't be recursive
70 | expect_equal(
71 | list_flatten(list_of(1, 2, 3)),
72 | list_of(1, 2, 3)
73 | )
74 | })
75 |
--------------------------------------------------------------------------------
/tests/testthat/test-list-simplify.R:
--------------------------------------------------------------------------------
1 | test_that("simplifies using vctrs principles", {
2 | expect_identical(list_simplify(list(1, 2L)), c(1, 2))
3 | expect_equal(list_simplify(list("x", factor("y"))), c("x", "y"))
4 |
5 | x <- list(data.frame(x = 1), data.frame(y = 2))
6 | expect_equal(list_simplify(x), data.frame(x = c(1, NA), y = c(NA, 2)))
7 | })
8 |
9 | test_that("only uses outer names", {
10 | out <- list_simplify(list(a = 1, c(b = 1), c = c(d = 1)))
11 | expect_named(out, c("a", "", "c"))
12 | })
13 |
14 | test_that("ptype is enforced", {
15 | expect_equal(list_simplify(list(1, 2), ptype = double()), c(1, 2))
16 | expect_snapshot(list_simplify(list(1, 2), ptype = character()), error = TRUE)
17 | # even if `strict = FALSE`
18 | expect_snapshot(list_simplify(list(1, 2), ptype = character(), strict = FALSE), error = TRUE)
19 | })
20 |
21 | test_that("strict simplification will error", {
22 | expect_snapshot(error = TRUE, {
23 | list_simplify(list(mean))
24 | list_simplify(list(1, "a"))
25 | list_simplify(list(1, 1:2))
26 | list_simplify(list(data.frame(x = 1), data.frame(x = 1:2)))
27 | list_simplify(list(1, 2), ptype = character())
28 | })
29 | })
30 |
31 | test_that("simplification requires length-1 vectors with common type", {
32 | expect_equal(list_simplify(list(mean), strict = FALSE), list(mean))
33 | expect_equal(list_simplify(list(1, 2:3), strict = FALSE), list(1, 2:3))
34 | expect_equal(list_simplify(list(1, "a"), strict = FALSE), list(1, "a"))
35 | })
36 |
37 | # argument checking -------------------------------------------------------
38 |
39 | test_that("list_simplify() validates inputs", {
40 | expect_snapshot(list_simplify(1:5), error = TRUE)
41 | expect_snapshot(list_simplify(list(), strict = NA), error = TRUE)
42 | })
43 |
44 | test_that("list_simplify_internal() validates inputs", {
45 | expect_snapshot(list_simplify_internal(list(), simplify = 1), error = TRUE)
46 | expect_snapshot(list_simplify_internal(list(), simplify = FALSE, ptype = integer()), error = TRUE)
47 | })
48 |
--------------------------------------------------------------------------------
/tests/testthat/test-lmap.R:
--------------------------------------------------------------------------------
1 | test_that("lmap output is list if input is list", {
2 | x <- list(a = 1:4, b = letters[5:7], c = 8:9, d = letters[10])
3 | maybe_rep <- function(x) {
4 | n <- rpois(1, 2)
5 | out <- rep_len(x, n)
6 | if (length(out) > 0) {
7 | names(out) <- paste0(names(x), seq_len(n))
8 | }
9 | out
10 | }
11 | expect_bare(lmap_at(x, "a", maybe_rep), "list")
12 | })
13 |
14 | test_that("lmap() returns a data frame if input is a data frame", {
15 | df <- data.frame(x = 1, y = 2)
16 |
17 | # as.data.frame() handles repeated names
18 | out <- lmap(df, function(x) as.data.frame(rep(x, 2)))
19 | expect_equal(out, data.frame(x = 1, x.1 = 1, y = 2, y.1 = 2))
20 |
21 | # even if we return bare lists
22 | out <- lmap(df, function(x) as.list(rep(x, 2)))
23 | expect_equal(out, data.frame(x = 1, x.1 = 1, y = 2, y.1 = 2))
24 | })
25 |
26 | test_that("lmap() can increase and decrease elements", {
27 | out <- lmap(list(0, 1, 2), ~ as.list(rep(.x, .x)))
28 | expect_equal(out, list(1, 2, 2))
29 | })
30 |
31 | test_that("lmap_at() only affects selected elements", {
32 | out <- lmap_at(list(0, 1, 2), c(1, 3), ~ as.list(rep(.x, .x)))
33 | expect_equal(out, list(1, 2, 2))
34 |
35 | out <- lmap_at(list(0, 1, 2), c(2, 3), ~ as.list(rep(.x, .x)))
36 | expect_equal(out, list(0, 1, 2, 2))
37 | })
38 |
39 | test_that("lmap_at can use tidyselect", {
40 | skip_if_not_installed("tidyselect")
41 | local_options(lifecycle_verbosity = "quiet")
42 |
43 | x <- lmap_at(mtcars, vars(tidyselect::contains("vs")), ~ .x + 10)
44 | expect_equal(x$vs[1], 10)
45 | })
46 |
47 | test_that("`.else` preserves false elements", {
48 | x <- list("a", 99)
49 | out <- lmap_if(x, is.character, ~ list(1, 2), .else = ~ list(3, 4))
50 | expect_equal(out, list(1, 2, 3, 4))
51 | })
52 |
53 | test_that("validates inputs", {
54 | expect_snapshot(error = TRUE, {
55 | lmap(list(1), ~ 1)
56 | lmap(list(1), environment())
57 | lmap(list(1), ~ 1, .else = environment())
58 | })
59 | })
60 |
--------------------------------------------------------------------------------
/tests/testthat/test-map-if-at.R:
--------------------------------------------------------------------------------
1 | test_that("map_if() and map_at() always return a list", {
2 | skip_if_not_installed("tibble")
3 | df <- tibble::tibble(x = 1, y = "a")
4 | expect_identical(map_if(df, is.character, ~"out"), list(x = 1, y = "out"))
5 | expect_identical(map_at(df, 1, ~"out"), list(x = "out", y = "a"))
6 | })
7 |
8 | test_that("map_at() works with tidyselect", {
9 | skip_if_not_installed("tidyselect")
10 | local_options(lifecycle_verbosity = "quiet")
11 |
12 | x <- list(a = "b", b = "c", aa = "bb")
13 | one <- map_at(x, vars(a), toupper)
14 | expect_identical(one$a, "B")
15 | expect_identical(one$aa, "bb")
16 | two <- map_at(x, vars(tidyselect::contains("a")), toupper)
17 | expect_identical(two$a, "B")
18 | expect_identical(two$aa, "BB")
19 | })
20 |
21 | test_that("negative .at omits locations", {
22 | x <- c(1, 2, 3)
23 | out <- map_at(x, -1, ~ .x * 2)
24 | expect_equal(out, list(1, 4, 6))
25 | })
26 |
27 | test_that("map_if requires predicate functions", {
28 | expect_snapshot(map_if(1:3, ~ NA, ~ "foo"), error = TRUE)
29 | })
30 |
31 | test_that("`.else` maps false elements", {
32 | expect_identical(map_if(-1:1, ~ .x > 0, paste, .else = ~ "bar", "suffix"), list("bar", "bar", "1 suffix"))
33 | })
34 |
--------------------------------------------------------------------------------
/tests/testthat/test-map-mapper.R:
--------------------------------------------------------------------------------
1 | # formulas ----------------------------------------------------------------
2 |
3 | test_that("can refer to first argument in three ways", {
4 | expect_equal(map_dbl(1, ~ . + 1), 2)
5 | expect_equal(map_dbl(1, ~ .x + 1), 2)
6 | expect_equal(map_dbl(1, ~ ..1 + 1), 2)
7 | })
8 |
9 | test_that("can refer to second arg in two ways", {
10 | expect_equal(map2_dbl(1, 2, ~ .x + .y + 1), 4)
11 | expect_equal(map2_dbl(1, 2, ~ ..1 + ..2 + 1), 4)
12 | })
13 |
14 | # vectors --------------------------------------------------------------
15 |
16 | # test_that(".null generates warning", {
17 | # expect_warning(map(1, 2, .null = NA), "`.null` is deprecated")
18 | # })
19 |
20 | test_that(".default replaces absent values", {
21 | x <- list(
22 | list(a = 1, b = 2, c = 3),
23 | list(a = 1, c = 2),
24 | NULL
25 | )
26 |
27 | expect_equal(map_dbl(x, 3, .default = NA), c(3, NA, NA))
28 | expect_equal(map_dbl(x, "b", .default = NA), c(2, NA, NA))
29 | })
30 |
31 | test_that(".default only replaces NULL elements", {
32 | x <- list(
33 | list(a = 1),
34 | list(a = numeric()),
35 | list(a = NULL),
36 | list()
37 | )
38 | expect_equal(map(x, "a", .default = NA), list(1, numeric(), NA, NA))
39 | })
40 |
41 | test_that("Additional arguments are ignored", {
42 | expect_equal(as_mapper(function() NULL, foo = "bar", foobar), function() NULL)
43 | })
44 |
45 | test_that("can supply length > 1 vectors", {
46 | expect_identical(as_mapper(1:2)(list(list("a", "b"))), "b")
47 | expect_identical(as_mapper(c("a", "b"))(list(a = list("a", b = "b"))), "b")
48 | })
49 |
50 |
51 | # primitive functions --------------------------------------------------
52 |
53 | test_that("primitive functions are wrapped", {
54 | expect_identical(as_mapper(`-`)(.y = 10, .x = 5), -5)
55 | expect_identical(as_mapper(`c`)(1, 3, 5), c(1, 3, 5))
56 | })
57 |
58 | test_that("syntactic primitives are wrapped", {
59 | expect_identical(as_mapper(`[[`)(mtcars, "cyl"), mtcars$cyl)
60 | expect_identical(as_mapper(`$`)(mtcars, cyl), mtcars$cyl)
61 | })
62 |
63 |
64 | # lists ------------------------------------------------------------------
65 |
66 | test_that("lists are wrapped", {
67 | mapper_list <- as_mapper(list("mpg", 5))(mtcars)
68 | base_list <- mtcars[["mpg"]][[5]]
69 | expect_identical(mapper_list, base_list)
70 | })
71 |
--------------------------------------------------------------------------------
/tests/testthat/test-map-raw.R:
--------------------------------------------------------------------------------
1 | test_that("_raw funtions are deprecated", {
2 | expect_snapshot({
3 | . <- map_raw(list(), ~ .x)
4 | . <- map2_raw(list(), list(), ~ .x)
5 | . <- imap_raw(list(), ~ .x)
6 | . <- pmap_raw(list(), ~ .x)
7 | . <- flatten_raw(list())
8 | })
9 | })
10 |
11 | test_that("_raw functions still work", {
12 | local_options(lifecycle_verbosity = "quiet")
13 | expect_equal(map_raw("a", charToRaw), charToRaw("a"))
14 | expect_identical(map_raw(set_names(list()), identity), named(raw()))
15 |
16 | expect_identical(map2_raw(set_names(list()), list(), identity), named(raw()))
17 | expect_equal(imap_raw(as.raw(12), rawShift), rawShift(as.raw(12), 1) )
18 |
19 | expect_bare(pmap_raw(list(1:3), as.raw), "raw")
20 | expect_identical(pmap_raw(list(named(list())), identity), named(raw()))
21 |
22 | expect_equal(flatten_raw(list(as.raw(1))), as.raw(1))
23 | })
24 |
--------------------------------------------------------------------------------
/tests/testthat/test-modify-tree.R:
--------------------------------------------------------------------------------
1 | test_that("can modify leaves", {
2 | expect_equal(
3 | modify_tree(c(1, 1, 1), leaf = ~ .x + 9),
4 | c(10, 10, 10)
5 | )
6 |
7 | expect_equal(
8 | modify_tree(list(1, list(1, list(1))), leaf = ~ .x + 9),
9 | list(10, list(10, list(10)))
10 | )
11 | })
12 |
13 | test_that("can modify nodes", {
14 | expect_equal(
15 | modify_tree(list(1, list(2, list(3))), post = list_flatten),
16 | list(1, 2, 3)
17 | )
18 | })
19 |
20 | test_that("default doesn't recurse into data frames, but can customise", {
21 | local_options(stringsAsFactors = FALSE)
22 |
23 | x <- list(data.frame(x = 1), data.frame(y = 2))
24 | expect_equal(
25 | modify_tree(x, leaf = class),
26 | list("data.frame", "data.frame")
27 | )
28 | expect_equal(
29 | modify_tree(x, leaf = class, is_node = is.list),
30 | list(data.frame(x = "numeric"), data.frame(y = "numeric"))
31 | )
32 | })
33 |
34 | test_that("leaf() is applied to non-node input", {
35 | expect_equal(modify_tree(1:3, leaf = identity), 1:3)
36 | })
37 |
38 | test_that("validates inputs", {
39 | expect_snapshot(error = TRUE, {
40 | modify_tree(list(), is_node = ~ 1)
41 | modify_tree(list(), is_node = 1)
42 | })
43 | })
44 |
--------------------------------------------------------------------------------
/tests/testthat/test-pluck-depth.R:
--------------------------------------------------------------------------------
1 | test_that("depth of non-vectors is 0", {
2 | expect_equal(pluck_depth(NULL), 0L)
3 | expect_equal(pluck_depth(mean), 0L)
4 | })
5 |
6 | test_that("depth of atomic vector is 1", {
7 | expect_equal(pluck_depth(1:10), 1)
8 | expect_equal(pluck_depth(letters), 1)
9 | expect_equal(pluck_depth(c(TRUE, FALSE)), 1)
10 | })
11 |
12 | test_that("depth of nested is depth of deepest element + 1", {
13 | x <- list(
14 | NULL,
15 | list(),
16 | list(list())
17 | )
18 |
19 | depths <- map_int(x, pluck_depth)
20 | expect_equal(depths, c(0, 1, 2))
21 | expect_equal(pluck_depth(x), 3)
22 | })
23 |
24 | test_that("vec_depth() is deprecated", {
25 | expect_snapshot({
26 | . <- vec_depth(list())
27 | })
28 | })
29 |
--------------------------------------------------------------------------------
/tests/testthat/test-rate.R:
--------------------------------------------------------------------------------
1 | test_that("new_rate() creates rate objects", {
2 | rate <- new_rate("foo", jitter = FALSE, max_times = 10)
3 | expect_identical(rate$state$i, 0L)
4 | expect_identical(rate$max_times, 10)
5 | expect_false(rate$jitter)
6 | })
7 |
8 | test_that("can bump and reset count", {
9 | rate <- new_rate("foo")
10 |
11 | rate_bump_count(rate)
12 | rate_bump_count(rate)
13 | expect_identical(rate_count(rate), 2L)
14 |
15 | rate_reset(rate)
16 | expect_identical(rate_count(rate), 0L)
17 | })
18 |
19 | test_that("rates have print methods", {
20 | expect_snapshot({
21 | # Also checks infinite `max_times` prints properly
22 | rate_delay(20, max_times = Inf)
23 |
24 | rate_backoff()
25 | })
26 | })
27 |
28 | test_that("rate_delay() delays", {
29 | rate <- rate_delay(
30 | pause = 0.02,
31 | max_times = 3
32 | )
33 |
34 | rate_sleep(rate, quiet = FALSE)
35 |
36 | rate_reset(rate)
37 |
38 | msg <- catch_cnd(rate_sleep(rate))
39 | expect_true(inherits_all(msg, c("purrr_condition_rate_init", "condition")))
40 |
41 | msg <- catch_cnd(rate_sleep(rate, quiet = FALSE))
42 | expect_true(inherits_all(msg, c("purrr_message_rate_retry", "message")))
43 | expect_identical(msg$length, 0.02)
44 |
45 | msg <- catch_cnd(rate_sleep(rate, quiet = FALSE))
46 | expect_identical(msg$length, 0.02)
47 |
48 | expect_snapshot(rate_sleep(rate), error = TRUE)
49 | expect_snapshot(rate_sleep(rate), error = TRUE)
50 | })
51 |
52 | test_that("rate_backoff() backs off", {
53 | rate <- rate_backoff(
54 | pause_base = 0.02,
55 | pause_min = 0,
56 | jitter = FALSE
57 | )
58 |
59 | msg <- catch_cnd(rate_sleep(rate))
60 | expect_true(inherits_all(msg, c("purrr_condition_rate_init", "condition")))
61 |
62 | msg <- catch_cnd(rate_sleep(rate, quiet = FALSE))
63 | expect_true(inherits_all(msg, c("purrr_message_rate_retry", "message")))
64 | expect_identical(msg$length, 0.04)
65 |
66 | msg <- catch_cnd(rate_sleep(rate, quiet = FALSE))
67 | expect_identical(msg$length, 0.08)
68 |
69 | expect_snapshot(rate_sleep(rate), error = TRUE)
70 | expect_snapshot(rate_sleep(rate), error = TRUE)
71 | })
72 |
73 | test_that("rate_sleep() checks that rate is still valid", {
74 | rate <- rate_delay(1, max_times = 0)
75 | expect_snapshot(rate_sleep(rate), error = TRUE)
76 | expect_snapshot(rate_sleep(rate), error = TRUE)
77 | })
78 |
79 |
--------------------------------------------------------------------------------
/tests/testthat/test-superseded-map-df.R:
--------------------------------------------------------------------------------
1 | test_that("row and column binding work", {
2 | skip_if_not_installed("dplyr")
3 | local_name_repair_quiet()
4 |
5 | mtcar_mod <- mtcars %>%
6 | split(.$cyl) %>%
7 | map(~ lm(mpg ~ wt, data = .x))
8 |
9 | f_coef <- function(x) as.data.frame(t(as.matrix(coef(x))))
10 | expect_length(mtcar_mod %>% map_dfr(f_coef), 2)
11 | expect_length(mtcar_mod %>% map_dfc(f_coef), 6)
12 | })
13 |
14 | test_that("data frame imap works", {
15 | skip_if_not_installed("dplyr")
16 | x <- set_names(1:3)
17 | expect_identical(imap_dfc(x, paste), imap_dfr(x, paste))
18 | })
19 |
20 | test_that("outputs are suffixes have correct type for data frames", {
21 | skip_if_not_installed("dplyr")
22 | local_name_repair_quiet()
23 |
24 | local_options(rlang_message_verbosity = "quiet")
25 | x <- 1:3
26 | expect_s3_class(pmap_dfr(list(x), as.data.frame), "data.frame")
27 | expect_s3_class(pmap_dfc(list(x), as.data.frame), "data.frame")
28 | })
29 |
--------------------------------------------------------------------------------
/tests/testthat/test-superseded-simplify.R:
--------------------------------------------------------------------------------
1 | test_that("can_simplify() understands vector molds", {
2 | x <- as.list(1:3)
3 | x2 <- c(x, list(1:3))
4 | expect_true(can_simplify(x, integer(1)))
5 | expect_false(can_simplify(x, character(1)))
6 | expect_false(can_simplify(x2, integer(1)))
7 |
8 | x3 <- list(1:2, 3:4, 5:6)
9 | expect_true(can_simplify(x3, integer(2)))
10 | expect_false(can_simplify(x, integer(2)))
11 | })
12 |
13 | test_that("can_simplify() understands types as strings", {
14 | x <- as.list(1:3)
15 | expect_true(can_simplify(x, "integer"))
16 | expect_false(can_simplify(x, "character"))
17 | })
18 |
19 | test_that("integer is coercible to double", {
20 | x <- list(1L, 2L)
21 | expect_true(can_simplify(x, "numeric"))
22 | expect_true(can_simplify(x, numeric(1)))
23 | expect_true(can_simplify(x, "double"))
24 | expect_true(can_simplify(x, double(1)))
25 | })
26 |
27 | test_that("numeric is an alias for double", {
28 | expect_true(can_simplify(list(1, 2), "numeric"))
29 | })
30 |
31 | test_that("double is not coercible to integer", {
32 | expect_false(can_simplify(list(1, 2), "integer"))
33 | })
34 |
--------------------------------------------------------------------------------
/tools/examples.R:
--------------------------------------------------------------------------------
1 | if (getRversion() < "4.1") {
2 | dir.create("man/macros", showWarnings = FALSE, recursive = TRUE)
3 | cat(
4 | paste(
5 | "\\renewcommand{\\examples}{\\section{Examples}{",
6 | "These examples are designed to work in R >= 4.1 so that we can take",
7 | "advantage of modern syntax like the base pipe (\\verb{|>}) and the ",
8 | "function shorthand (\\verb{\\(x) x + 1}). They might not work on the ",
9 | "version of R that you're using.",
10 | "\\preformatted{#1}}}",
11 | collapse = ""
12 | ),
13 | file = "man/macros/examples.Rd"
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *.R
3 |
--------------------------------------------------------------------------------
/vignettes/other-langs.Rmd:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Functional programming in other languages"
3 | output: rmarkdown::html_vignette
4 | vignette: >
5 | %\VignetteIndexEntry{Functional programming in other languages}
6 | %\VignetteEngine{knitr::rmarkdown}
7 | %\VignetteEncoding{UTF-8}
8 | ---
9 |
10 | purrr draws inspiration from many related tools:
11 |
12 | * List operations defined in the Haskell [prelude][haskell]
13 |
14 | * Scala's [list methods][scala].
15 |
16 | * Functional programming libraries for javascript:
17 | [underscore.js](http://underscorejs.org),
18 | [lodash](https://lodash.com) and
19 | [lazy.js](http://danieltao.com/lazy.js/).
20 |
21 | * [rlist](https://renkun-ken.github.io/rlist/), another R package to support working
22 | with lists. Similar goals but somewhat different philosophy.
23 |
24 | However, the goal of purrr is not to try and simulate a purer functional programming language in R; we don't want to implement a second-class version of Haskell in R. The goal is to give you similar expressiveness to an FP language, while allowing you to write code that looks and works like R:
25 |
26 | * Instead of point free (tacit) style, we use the pipe, `|>`, to write code
27 | that can be read from left to right.
28 |
29 | * Instead of currying, we use `...` to pass in extra arguments.
30 |
31 | * Before R 4.1, anonymous functions were verbose, so we provide two convenient shorthands.
32 | For unary functions, `~ .x + 1` is equivalent to `function(.x) .x + 1`.
33 |
34 | * R is weakly typed, so we need `map` variants that describe the output type
35 | (like `map_int()`, `map_dbl()`, etc) because we don't know the return type of `.f`.
36 |
37 | * R has named arguments, so instead of providing different functions for
38 | minor variations (e.g. `detect()` and `detectLast()`) we use a named
39 | argument, `.right`. Type-stable functions are easy to reason about so
40 | additional arguments will never change the type of the output.
41 |
42 | [scala]:https://www.scala-lang.org/api/current/index.html
43 | [haskell]:http://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#g:11
44 |
--------------------------------------------------------------------------------