[
  {
    "path": ".Rbuildignore",
    "content": "#----------------------------\n# Git and SVN related\n#----------------------------\n^.svn\n^.git\n^.make\n^INSTALL[.]md$\n^OVERVIEW[.]md$\n^README[.]md$\n^CONDUCT[.]md$\n^CONTRIBUTING[.]md$\n\n#----------------------------\n# devtools\n#----------------------------\n^revdep\n\n#----------------------------\n# Travis-CI et al.\n#----------------------------\n^[.]travis[.]yml$\n^travis-tool[.]sh$\n^pkg-build[.]sh$\n^appveyor[.]yml$\n^covr-utils.R$\n^[.]covr[.]R$\n^[.]covr[.]rds$\n\n#----------------------------\n# R related\n#----------------------------\nRplots.pdf$\n^cran-comments[.].*$\n^vignettes/.*[.](pdf|PDF)$\n^vignettes/.*[.](r|R)$\n^vignettes/[.]install_extras$\n^Makefile$\n^incl\n^NAMESPACE,.*[.]txt$\n^nohup.*$\n^[.]R\n^[.]benchmark\n^[.]devel\n^[.]test\n^[.]check\n^.*[.]tar[.]gz$\n\n#----------------------------\n# Package specific\n#----------------------------\n^[.]BatchJobs[.]R$\n^[.]future\n\n#----------------------------\n# Miscellaneous\n#----------------------------\n^.ghi\n^.issues\n^.local\n^docs\n^pkgdown\n[.]Rdump\n^\\.github$\n"
  },
  {
    "path": ".Rinstignore",
    "content": "# Certain LaTeX files (e.g. bib, bst, sty) must be part of the build \n# such that they are available for R CMD check.  These are excluded\n# from the install using .Rinstignore in the top-level directory\n# such as this one.\ndoc/.*[.](bib|bst|sty)$\n"
  },
  {
    "path": ".github/.gitignore",
    "content": "*.html\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve (Please use future's 'Discussions' for Q&A)\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n(Please use <https://github.com/futureverse/future/discussions> for Q&A)\n\n**Describe the bug**\nA clear and concise description of what the bug is.  \n\n**Reproduce example**\nA reproducible example using R code.\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Session information**\nPlease share your session information, e.g.\n\n```r\n> sessionInfo()\n```\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "lank_issues_enabled: true\ncontact_links:\n  - name: Support & Discussions\n    url: https://github.com/futureverse/future/discussions/\n    about: Got a question? Something is not working? Want to share an idea?\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project (Please use future's 'Discussions' for Q&A)\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n(Please use <https://github.com/futureverse/future/discussions> for Q&A)\n\n**Wish or feature request**\nA clear and concise description of what the problem is. For example, I would like to be able to ...\n"
  },
  {
    "path": ".github/workflows/R-CMD-check.yaml",
    "content": "on: [push, pull_request]\n\nname: R-CMD-check\n\njobs:\n  R-CMD-check:\n    if: \"! contains(github.event.head_commit.message, '[ci skip]')\"    \n\n    timeout-minutes: 30\n\n    runs-on: ${{ matrix.config.os }}\n\n    name: ${{ matrix.config.os }} (${{ matrix.config.r }}) ${{ matrix.config.label }}\n\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n          - {os: windows-latest, r: 'devel'    }\n          - {os: windows-latest, r: 'release'  }\n          - {os: windows-latest, r: 'oldrel'   }\n          - {os: macOS-latest,   r: 'devel'    }\n          - {os: macOS-latest,   r: 'release'  }\n          - {os: macOS-latest,   r: 'oldrel'   }\n          - {os: ubuntu-latest,  r: 'devel', strict: true, label: 'strict' }\n          - {os: ubuntu-latest,  r: 'release'  }\n          - {os: ubuntu-latest,  r: 'oldrel'   }\n          - {os: ubuntu-latest,  r: 'oldrel-1' }\n          - {os: ubuntu-latest,  r: 'oldrel-2' }\n          - {os: ubuntu-latest,  r: '4.0'      }\n          - {os: ubuntu-latest,  r: 'release'  , language: ko,    label: ko    }\n          - {os: ubuntu-latest,  r: 'release'  , globals_keepWhere: true, label: 'keepWhere' }\n          - {os: ubuntu-latest,  r: 'release'  , globals_keepWhere: false, label: '!keepWhere' }\n          - {os: windows-latest, r: 'devel', future_version: develop, label: 'w/ future-develop' }\n          - {os: ubuntu-latest,  r: 'release', future_version: develop, label: 'w/ future-develop' }\n \n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n      R_KEEP_PKG_SOURCE: yes\n      R_REMOTES_NO_ERRORS_FROM_WARNINGS: true\n      ## Test in other locale (optional)\n      LANGUAGE: ${{ matrix.config.language }}\n      ## R CMD check\n      _R_CHECK_CRAN_INCOMING_: false\n      _R_CHECK_MATRIX_DATA_: true\n      _R_CHECK_SUGGESTS_ONLY_: true\n      _R_CHECK_THINGS_IN_TEMP_DIR_: true\n      ## Specific to 'rcmdcheck'\n      RCMDCHECK_ERROR_ON: note\n      ## Specific to futures\n      R_FUTURE_RNG_ONMISUSE: error\n      R_FUTURE_GLOBALS_KEEPWHERE: ${{ matrix.config.globals_keepWhere }}\n      R_FUTURE_VERSION: ${{ matrix.config.future_version }}\n      R_GLOBALS_VERSION: ${{ matrix.config.globals_version }}\n      \n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: r-lib/actions/setup-pandoc@v2\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          r-version: ${{ matrix.config.r }}\n          http-user-agent: ${{ matrix.config.http-user-agent }}\n          use-public-rspm: true\n          \n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::rcmdcheck\n          needs: check\n\n      - name: Install package itself (special case)\n        run: |\n          install.packages(\".\", repos = NULL, type = \"source\")  ## needed by parallel workers\n        shell: Rscript {0}\n\n      - name: Test with specific future version?\n        run: |\n          globals_version <- Sys.getenv(\"R_GLOBALS_VERSION\")\n          if (nzchar(globals_version)) {\n            install.packages(\"remotes\")\n            remotes::install_github(\"futureverse/future\", ref=globals_version)\n          }\n          future_version <- Sys.getenv(\"R_FUTURE_VERSION\")\n          if (nzchar(future_version)) {\n            install.packages(\"remotes\")\n            remotes::install_github(\"futureverse/future\", ref=future_version)\n          }\n        shell: Rscript {0}\n\n      - name: Session info\n        run: |\n          options(width = 100)\n          parallelly::availableCores(which = \"all\")\n          sapply(c(physical_cores = FALSE, logical_cores = TRUE), parallel::detectCores)\n          if (require(RhpcBLASctl, quietly=TRUE)) c(get_num_procs = get_num_procs(), get_num_cores = get_num_cores(), blas_get_num_procs = blas_get_num_procs(), omp_get_num_procs = omp_get_num_procs(), omp_get_max_threads = omp_get_max_threads())\n          capabilities()\n          pkgs <- installed.packages()[, \"Package\"]\n          sessioninfo::session_info(pkgs, include_base = TRUE)\n          ## Verify LANGUAGE settings by generating a translatable error\n          cat(sprintf(\"LANGUAGE=%s\\n\", sQuote(Sys.getenv(\"LANGUAGE\"))))\n          cat(sprintf(\"locales: %s\\n\", sQuote(Sys.getlocale())))\n          tryCatch(log(\"a\"), error = conditionMessage)\n        shell: Rscript {0}\n\n      - name: Check\n        run: |\n          if (\"${{ matrix.config.strict }}\" == \"true\") {\n            Sys.setenv(NOT_CRAN = \"true\")\n            Sys.setenv(R_FUTURE_GLOBALENV_ONMISUSE = \"error\")\n            Sys.setenv(R_FUTURE_RNG_ONMISUSE = \"error\")\n            Sys.setenv(R_FUTURE_FUTURE_EARLYSIGNAL = \"defunct\")\n            Sys.setenv(R_FUTURE_FUTURE_LOCAL = \"defunct\")\n            Sys.setenv(R_FUTURE_FUTURE_GC = \"defunct\")\n            Sys.setenv(R_FUTURE_PLAN_EARLYSIGNAL = \"defunct\")\n            Sys.setenv(R_FUTURE_RESOLVED_RUN = \"defunct\")\n          }\n          if (nzchar(Sys.getenv(\"R_FUTURE_PLAN\"))) Sys.setenv(RCMDCHECK_ERROR_ON = \"error\")\n          rcmdcheck::rcmdcheck(\n            args = c(\"--no-manual\", \"--as-cran\"),\n            check_dir = \"check\"\n          )\n        shell: Rscript {0}\n\n      - name: Upload check results\n        if: failure()\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ runner.os }}-r${{ matrix.config.r }}-results\n          path: check\n"
  },
  {
    "path": ".github/workflows/rhub.yaml",
    "content": "# R-hub's generic GitHub Actions workflow file. It's canonical location is at\n# https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml\n# You can update this file to a newer version using the rhub2 package:\n#\n# rhub::rhub_setup()\n#\n# It is unlikely that you need to modify this file manually.\n\nname: R-hub\nrun-name: \"${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}\"\n\non:\n  workflow_dispatch:\n    inputs:\n      config:\n        description: 'A comma separated list of R-hub platforms to use.'\n        type: string\n        default: 'linux,windows,macos'\n      name:\n        description: 'Run name. You can leave this empty now.'\n        type: string\n      id:\n        description: 'Unique ID. You can leave this empty now.'\n        type: string\n\njobs:\n\n  setup:\n    runs-on: ubuntu-latest\n    outputs:\n      containers: ${{ steps.rhub-setup.outputs.containers }}\n      platforms: ${{ steps.rhub-setup.outputs.platforms }}\n\n    steps:\n    # NO NEED TO CHECKOUT HERE\n    - uses: r-hub/actions/setup@v1\n      with:\n        config: ${{ github.event.inputs.config }}\n      id: rhub-setup\n\n  linux-containers:\n    needs: setup\n    if: ${{ needs.setup.outputs.containers != '[]' }}\n    runs-on: ubuntu-latest\n    name: ${{ matrix.config.label }}\n    strategy:\n      fail-fast: false\n      matrix:\n        config: ${{ fromJson(needs.setup.outputs.containers) }}\n    container:\n      image: ${{ matrix.config.container }}\n\n    steps:\n      - uses: r-hub/actions/checkout@v1\n      - uses: r-hub/actions/platform-info@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n      - uses: r-hub/actions/setup-deps@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n      - uses: r-hub/actions/run-check@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n\n  other-platforms:\n    needs: setup\n    if: ${{ needs.setup.outputs.platforms != '[]' }}\n    runs-on: ${{ matrix.config.os }}\n    name: ${{ matrix.config.label }}\n    strategy:\n      fail-fast: false\n      matrix:\n        config: ${{ fromJson(needs.setup.outputs.platforms) }}\n\n    steps:\n      - uses: r-hub/actions/checkout@v1\n      - uses: r-hub/actions/setup-r@v1\n        with:\n          job-config: ${{ matrix.config.job-config }}\n          token: ${{ secrets.RHUB_TOKEN }}\n      - uses: r-hub/actions/platform-info@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n      - uses: r-hub/actions/setup-deps@v1\n        with:\n          job-config: ${{ matrix.config.job-config }}\n          token: ${{ secrets.RHUB_TOKEN }}\n      - uses: r-hub/actions/run-check@v1\n        with:\n          job-config: ${{ matrix.config.job-config }}\n          token: ${{ secrets.RHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/test-coverage.yaml",
    "content": "on:\n  workflow_dispatch:  # Enables manual triggering\n\nname: test-coverage.yaml\n\npermissions: read-all\n\njobs:\n  test-coverage:\n    runs-on: ubuntu-latest\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Assert CODECOV_TOKEN is set\n        run: |\n          if [[ -z \"${{secrets.CODECOV_TOKEN}}\" ]]; then\n            >&2 echo \"::error::ERROR: 'secrets.CODECOV_TOKEN' not set\"\n            exit 1\n          fi\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::covr, any::xml2, any::remotes\n          needs: coverage\n\n      - name: Install itself\n        run: |\n          install.packages(\".\", repos = NULL, type = \"source\")\n          remotes::install_github(\"futureverse/globals\", ref = \"develop\")\n          remotes::install_github(\"futureverse/future\", ref = \"develop\")\n        shell: Rscript {0}\n\n      - name: Test coverage\n        run: |\n          cov <- covr::package_coverage(\n            quiet = FALSE,\n            clean = FALSE,\n            install_path = file.path(normalizePath(Sys.getenv(\"RUNNER_TEMP\"), winslash = \"/\"), \"package\")\n          )\n          print(cov)\n          covr::to_cobertura(cov)\n        shell: Rscript {0}\n\n      - uses: codecov/codecov-action@v4\n        with:\n          fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }}\n          file: ./cobertura.xml\n          plugin: noop\n          disable_search: true\n          token: ${{ secrets.CODECOV_TOKEN }}\n\n      - name: Upload test results\n        if: failure()\n        uses: actions/upload-artifact@v4\n        with:\n          name: coverage-test-failures\n          path: ${{ runner.temp }}/package\n"
  },
  {
    "path": ".gitignore",
    "content": ".Rhistory\n*~\n**/*~\n.R\n.benchmark\n.check\n.devel\n.test\n*.o\n*.dll\n*.Rout\n.RData\n*.Rproj*\n*.swp\n.covr.rds\n.future\n.ghi\n.issues\n.make\n.local\nrevdep/data.sqlite\nrevdep/cache\nrevdep/checks\nrevdep/library\ndocs/\n.Rdump\n"
  },
  {
    "path": "CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "\n# Contributing to the 'future.apply' package\n\nThis Git repository uses the [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/) branching model (the [`git flow`](https://github.com/petervanderdoes/gitflow-avh) extension is useful for this).  The [`develop`](https://github.com/futureverse/future.apply/tree/develop) branch contains the latest contributions and other code that will appear in the next release, and the [`master`](https://github.com/futureverse/future.apply) branch contains the code of the latest release, which is exactly what is currently on [CRAN](https://cran.r-project.org/package=future.apply).\n\nContributing to this package is easy.  Just send a [pull request](https://help.github.com/articles/using-pull-requests/).  When you send your PR, make sure `develop` is the destination branch on the [future.apply repository](https://github.com/futureverse/future.apply).  Your PR should pass `R CMD check --as-cran`, which will also be checked by  <a href=\"https://github.com/futureverse/future.apply/actions?query=workflow%3AR-CMD-check\">GitHub Actions</a> and  when the PR is submitted.\n\nWe abide to the [Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/) of Contributor Covenant.\n"
  },
  {
    "path": "DESCRIPTION",
    "content": "Package: future.apply\nVersion: 1.20.2-9000\nTitle: Apply Function to Elements in Parallel using Futures\nDepends:\n    R (>= 3.2.0),\n    future (>= 1.49.0)\nImports:\n    globals,\n    parallel,\n    utils\nSuggests:\n    datasets,\n    stats,\n    tools,\n    listenv,\n    R.rsp,\n    markdown\nVignetteBuilder: R.rsp\nAuthors@R: c(person(\"Henrik\", \"Bengtsson\",\n                    role = c(\"aut\", \"cre\", \"cph\"),\n                    email = \"henrikb@braju.com\",\n                    comment = c(ORCID = \"0000-0002-7579-5165\")),\n             person(\"R Core Team\", role = c(\"cph\", \"ctb\")))\nDescription: Implementations of apply(), by(), eapply(), lapply(), Map(), .mapply(), mapply(), replicate(), sapply(), tapply(), and vapply() that can be resolved using any future-supported backend, e.g. parallel on the local machine or distributed on a compute cluster. These future_*apply() functions come with the same pros and cons as the corresponding base-R *apply() functions but with the additional feature of being able to be processed via the future framework <doi:10.32614/RJ-2021-048>.\nLicense: GPL (>= 2)\nLazyLoad: TRUE\nURL: https://future.apply.futureverse.org, https://github.com/futureverse/future.apply\nBugReports: https://github.com/futureverse/future.apply/issues\nLanguage: en-US\nEncoding: UTF-8\nRoxygenNote: 7.3.3\nRoxygen: list(markdown = TRUE)\n"
  },
  {
    "path": "Makefile",
    "content": "include .make/Makefile\n"
  },
  {
    "path": "NAMESPACE",
    "content": "# Generated by roxygen2: do not edit by hand\n\nS3method(future_by,data.frame)\nS3method(future_by,default)\nS3method(future_kernapply,default)\nS3method(future_kernapply,ts)\nexport(future_.mapply)\nexport(future_Filter)\nexport(future_Map)\nexport(future_apply)\nexport(future_by)\nexport(future_eapply)\nexport(future_kernapply)\nexport(future_lapply)\nexport(future_mapply)\nexport(future_replicate)\nexport(future_sapply)\nexport(future_tapply)\nexport(future_vapply)\nimportFrom(future,Future)\nimportFrom(future,FutureError)\nimportFrom(future,FutureInterruptError)\nimportFrom(future,as.FutureGlobals)\nimportFrom(future,cancel)\nimportFrom(future,future)\nimportFrom(future,getGlobalsAndPackages)\nimportFrom(future,nbrOfWorkers)\nimportFrom(future,resolve)\nimportFrom(future,value)\nimportFrom(globals,findGlobals)\nimportFrom(globals,globalsByName)\nimportFrom(parallel,splitIndices)\nimportFrom(stats,end)\nimportFrom(stats,frequency)\nimportFrom(stats,kernapply)\nimportFrom(stats,ts)\nimportFrom(utils,capture.output)\nimportFrom(utils,globalVariables)\nimportFrom(utils,head)\nimportFrom(utils,packageVersion)\nimportFrom(utils,str)\n"
  },
  {
    "path": "NEWS.md",
    "content": "# Version (development version)\n\n * ...\n\n\n# Version 1.20.2 [2026-02-19]\n\n## Miscellaneous\n\n * This is a maintenance update with internal updates only.\n\n\n# Version 1.20.1 [2025-12-08]\n\n## Bug Fixes\n\n * `future_apply(..., future.globals = list(...))` would produce\n   'Error in if (chunk_size > maxSize) { : missing value where\n   TRUE/FALSE needed'.\n \n\n# Version 1.20.0 [2025-06-06]\n\n## Significant changes\n\n * All **future.apply** functions will now cancel any remaining\n   non-resolved futures if one of the futures produces an error, or a\n   user interrupt (Ctrl-C) is detected. If the backend where the\n   futures are running supports it, the canceled futures are also\n   interrupted, which results in compute resources being freed up\n   sooner and the **future.apply** function returning sooner.\n\n## New Features\n\n * Added `future_Filter()`, which is parallel version of\n   `base::Filter()`.\n\n * Added `future_kernapply()`, which is parallel version of\n   `stats::kernapply()`.\n\n * Now **future.apply** lets **future** take care of the generation of\n   parallel RNG seed. Consolidating random number generation to the\n   core package will allow us to add central support for custom\n   parallel RNG methods beyond the built-in L'Ecuyer-CMRG method.\n\n## Deprecated and Defunct\n\n * Specifying the function `FUN` for `future_by()` as a character\n   string is defunct. It should be specified as a function, e.g. `FUN\n   = sqrt` and ``FUN = `[[` ``, which is what `base::by()`\n   requires. Use of a string has been deprecated since\n   **future.apply** 1.10.0 (2022-11-04).\n\n\n# Version 1.11.3 [2024-10-27]\n\n## Bug Fixes\n\n * Use of `future.seed = TRUE` could result in an error\n   `!any(seed_next != seed) is not TRUE` in rare cases.\n\n\n# Version 1.11.2 [2024-03-27]\n\n## Miscellaneous\n\n * Relaxed one unit test that triggered an error on 32-bit\n   architectures.\n\n\n# Version 1.11.1 [2023-12-19]\n\n## Bug Fixes\n\n * Option `future.globals.maxSize` was never passed down to parallel\n   workers.\n   \n * The assertion of argument `INDEX` of `future_tapply()` would fail\n   with another error in R (< 3.6.0), if `INDEX` was incorrect in the\n   first place.\n\n\n# Version 1.11.0 [2023-05-20]\n\n## Significant Changes\n\n * `future_tapply()` now accepts data frames as input, just as\n   `tapply()` does in R (>= 4.3.0).\n\n * In R (>= 4.3.0), `future_tapply(X, INDEX, ...)` now accepts `INDEX`\n   being a formula when `X` is a data frames, just as `tapply()` does\n   in R (>= 4.3.0).  An error is produced if used in R (< 4.3.0).\n\n * In R (>= 4.3.0), `future_by(X, INDICES, ...)` now accepts `INDICES`\n   being a formula when `X` is a data frames, just as `by()` does in\n   R (>= 4.3.0).  An error is produced if used in R (< 4.3.0).\n\n## New Features\n\n * Now **future** operators such as `%globals%`, `%seed%`, and `%stdout%`\n   can be used to control the corresponding `future.*` arguments, e.g.\n   `y <- future_lapply(1:3, FUN = my_fun) %seed% TRUE` is the same as\n   `y <- future_lapply(1:3, FUN = my_fun, future.seed = TRUE)`.\n\n## Bug Fixes\n\n * Contrary to `lapply(X, ...)`, `future_lapply(X, ...)` failed to use\n   method-specific `[[` subsetting, if the class of `X` implemented\n   one. `future_mapply()` and other functions had the same problem.\n   The reason was that when `X` is partitioned into chunks, it would\n   lose the class attribute before subsetting with `[[`.\n\n\n# Version 1.10.0 [2022-11-04]\n\n## Bug Fixes\n\n * Functions `future_eapply()`, `future_lapply()`, `future_sapply()`,\n   and `future_vapply()` failed if `FUN` was specified as the name of\n   a function rather than the function object itself,\n   e.g. `future_lapply(1:3, FUN = \"sqrt\")`.\n\n## Deprecated and Defunct\n\n * Specifying the function `FUN` for `future_by()` as a character\n   string is deprecated, because `base::by()` does not support it. It\n   should be specified as a function, e.g. `FUN = sqrt` and ``FUN =\n   `[[` ``.\n\n\n# Version 1.9.1 [2022-09-07]\n\n## Bug Fixes\n\n * Some warnings and errors showed the wrong call.\n\n## Miscellaneous\n\n * Fix some HTML5 issues in help pages.\n \n\n## Significant Changes\n\n * `future_mapply()` and `future_Map()` was updated to match the new\n   behavior of `mapply()` and `Map()` in R (>= 4.2.0), which follows\n   the \"max-or-0-if-any\" recycling rule.\n\n## Performance\n\n * Now captured standard output and conditions are deleted as soon as\n   they have been relayed. This requires **future** (>= 1.25.0).\n\n## Deprecated and Defunct\n\n * Removed moot argument `future.lazy` from all functions. Regardless\n   of setting it to TRUE or FALSE, futures would be resolved\n   momentarily and always before the apply returned.\n\n\n# Version 1.8.1 [2021-08-09]\n\n## Bug Fixes\n\n * `citEntry()` in CITATION used argument `notes` instead of `note`.\n \n\n# Version 1.8.0 [2021-08-09]\n\n## New Features\n\n * Add argument `future.envir` to all `future_nnn()` functions, which\n   is passed as argument `envir` to `future()`.\n\n * Add option `future.apply.debug` for debugging features specific to\n   this package.  It defaults to option `future.debug`.\n \n## Performance\n\n * Internal `getGlobalsAndPackagesXApply()` now avoids calculating the\n   object size of `...` arguments if option `future.globals.maxSize`\n   is +Inf.\n\n## Bug Fixes\n\n * `f <- function(...) future_lapply(X, function(x) list(...));\n   f(a=1)` would produce an error on 'unused argument (a = 1)\" with\n   the upcoming release of **future** 1.22.0.\n \n\n# Version 1.7.0 [2021-01-02]\n\n## New Features\n\n * The automatic capturing of conditions can be disabled by specifying\n   `future.conditions = NULL`.\n\n * Warnings and errors on using the RNG without specifying\n   `future.seed` are now tailored to the **future.apply** package.\n\n\n# Version 1.6.0 [2020-06-30]\n\n## Significant Changes\n\n * `future_apply()` gained argument `simplify`, which is added to\n   R-devel (to become R 4.1.0).\n\n## Bug Fixes\n\n * `future_apply(X, FUN, ...)` would pass all `future.*` arguments\n   except `future.globals`, `future.packages`, and `future.labels` to\n   the `FUN` function instead of processing them locally.  This would\n   often result in the `FUN` producing an error on \"unused argument\".\n   It also affected `future.seed` not being applied, which means for\n   some `FUN` functions that did not produce this error,\n   non-reproducible results could have been produced.\n   \n\n# Version 1.5.0 [2020-04-16]\n\n## New Features\n\n * Add `future_.mapply()` corresponding to `.mapply()` in the **base**\n   package.\n\n## Bug Fixes\n\n * `future_mapply()` would chunk up `MoreArgs` when `future.seed =\n   TRUE`.\n \n\n# Version 1.4.0 [2020-01-06]\n\n## New Features\n\n * Now all `future_nnn()` functions set a label on each future that\n   reflects the name of the `future_nnn()` function and the index of\n   the chunk, e.g.  `\"future_lapply-3\"`. The format can be controlled\n   by argument `future.label`.\n\n## Performance\n\n * The assertion of the maximum size of globals per chunk is now\n   significantly faster for `future_apply()`.\n\n## Bug Fixes\n\n * `future_lapply(X)` and `future_mapply(FUN, X)` would drop `names`\n   argument of the returned empty list when `length(X) == 0`.\n\n * Package could set `.Random.seed` to NULL, instead of removing it,\n   which in turn would produce a warning on \"'.Random.seed' is not an\n   integer vector but of type 'NULL', so ignored\" when the next random\n   number generated.\n \n\n# Version 1.3.0 [2019-06-17]\n\n## New Features\n\n * Now `future.conditions` defaults to the same as argument\n   `conditions` of `future::future()`.  If the latter changes, this\n   package will follow.\n \n * Debug messages are now prepended with a timestamp.\n\n## Bug Fixes\n\n * The error \"sprintf(...) : 'fmt' length exceeds maximal format\n   length 8192\" could be produced when debugging tried to report on\n   too many globals.\n \n\n# Version 1.2.0 [2019-03-06]\n\n## New Features\n\n * Added `future_by()`.\n\n## Bug Fixes\n\n * Attributes `add` and `ignore` of argument `future.globals` were\n   ignored although support for them was added in **future** (>=\n   1.10.0).\n\n * Validation of L'Ecuyer-CMRG RNG seeds failed in recent R devel.\n \n\n# Version 1.1.0 [2019-01-16]\n\n## Significant Changes\n\n * Added argument `future.stdout` and `future.conditions` for\n   controlling whether standard output and conditions (e.g. messages\n   and warnings) produced during the evaluation of futures should be\n   captured and relayed or not.  Standard output is guaranteed to be\n   relayed in the same order as it would when using sequential\n   processing.  Analogously for conditions.  However, standard output\n   is always relayed before conditions.  Errors are always relayed.\n   Relaying of non-error conditions requires **future** (>= 1.11.0).\n   \n## New Features\n\n * Elements can be processed in random order by setting attribute\n   `ordering` to `\"random\"` of argument `future.chunk.size` or\n   `future.scheduling`, e.g.  `future.chunk.size = structure(TRUE,\n   ordering = \"random\")`.  This can help improve load balancing in\n   cases where there is a correlation between processing time and\n   ordering of the elements.  Note that the order of the returned\n   values is not affected when randomizing the processing order.\n \n * Swapped order of arguments `future.lazy` and `future.seed` to be\n   consistent with ditto arguments of `future::future()`.\n \n\n# Version 1.0.1 [2018-08-26]\n\n## Documentation / Licence\n\n * The license is GPL (>= 2).  Previously it was documented as GPL (>=\n   2.1) but that is a non-existing GPL version.\n\n## Bug Fixes\n\n * For list objects `X` where `X != as.list(X), future_lapply(X)` did\n   not give the same result as `lapply(X)`.  Analogously for\n   `future_vapply(X)`.\n   \n * `future_mapply()` could drop class attribute on elements iterated\n   over, because `.subset()` was used internally instead of `` `[`()\n   ``.  For instance, iteration over `Date` objects were affected.\n\n\n# Version 1.0.0 [2018-06-19]\n\n## Significant Changes\n\n * License changed from LGPL (>= 2.1) to GPL (>= 2) to make sure it is\n   compatible with the source code adopted from R base's `apply()`,\n   `Map()`, `replicate()`, `sapply()`, and `tapply()`, which are all\n   GPL (>= 2).\n \n## New Features\n\n * Added `future_apply()`, `future_mapply()`, and `future_Map()`.\n\n * Added argument `future.chunk.size` as an alternative to argument\n   `future.scheduling` for controlling the average number of elements\n   processed per future (\"chunk\").  In R 3.5.0, the **parallel**\n   package introduced argument `chunk.size`.\n\n * The maximum total size of globals allowed (option\n   `future.globals.maxSize`) per future (\"chunk\") is now scaled up by\n   the number of elements processed by the future (\"chunk\") making the\n   protection approximately invariant to the amount of chunking\n   (arguments `future.scheduling` and `future.chunk.size`).\n \n## Bug Fixes\n\n * `future_lapply(X, ...)` did not search for globals in `X`.\n\n * `future_vapply()` did not return the same dimension names as\n   `vapply()` when `FUN.VALUE` had no names but `FUN(X[[1]])` had.\n \n## Software Quality\n\n * Test code coverage is 100%.\n \n \n# Version 0.2.0 [2018-05-01]\n\n## New Features\n\n * Added `future_eapply()`, `future_tapply()`, `future_vapply()`, and\n   `future_replicate()`.\n \n\n# Version 0.1.0 [2018-01-15]\n\n * Package submitted to CRAN.\n\n\n# Version 0.0.3 [2017-12-06]\n\n## Documentation\n\n * Vignette now covers the basics of the package and describes its\n   role in the R package ecosystem together with a road map going\n   forward.\n\n## Software Quality\n\n * Added more package tests.  Code coverage is currently at 100%.\n\n\n# Version 0.0.2 [2017-12-06]\n\n## Performance\n\n * `future_lapply(x, ...)` is now much faster and more memory\n   efficient for large `x` vectors because it uses internal `fold()`\n   function that is more efficient (memory and speed) version of\n   `base::Reduce(f, x)`, especially when `length(x)` is large.\n\n\n# Version 0.0.0-9000 [2017-08-31]\n\n## New Features\n\n * Added `future_sapply()`.\n\n * Added `future_lapply()` - originally from the **future** package.\n \n * Created package.\n"
  },
  {
    "path": "R/000.import.R",
    "content": "import_from <- function(name, mode = \"function\", default = NULL, package) {\n  ns <- getNamespace(package)\n  if (exists(name, mode = mode, envir = ns, inherits = FALSE)) {\n    get(name, mode = mode, envir = ns, inherits = FALSE)\n  } else if (!is.null(default)) {\n    default\n  } else {\n    stop(sprintf(\"No such '%s' %s: %s()\", package, mode, name))\n  }\n}\n\nimport_future <- function(name, mode = \"function\", default = NULL) {\n  import_from(name, mode = mode, default = default, package = \"future\")\n}\n\nimport_base <- function(name, mode = \"function\", default = NULL) {\n  import_from(name, mode = mode, default = default, package = \"base\")\n}\n"
  },
  {
    "path": "R/001.bquote.R",
    "content": "#' @importFrom utils globalVariables\nglobalVariables(c(\".\", \"..\"))\n\nbquote_compile <- import_future(\"bquote_compile\")\nbquote_apply <- import_future(\"bquote_apply\")\n\n"
  },
  {
    "path": "R/001.import_future_functions.R",
    "content": "## To be imported from 'future', if available\nsQuoteLabel <- NULL\n.debug <- NULL\n\nmake_rng_seeds <- import_future(\"make_rng_seeds\")\nget_random_seed <- import_future(\"get_random_seed\")\nset_random_seed <- import_future(\"set_random_seed\")\nnext_random_seed <- import_future(\"next_random_seed\")\nis_valid_random_seed <- import_future(\"is_valid_random_seed\")\nis_lecyer_cmrg_seed <- import_future(\"is_valid_random_seed\")\nas_lecyer_cmrg_seed <- import_future(\"as_lecyer_cmrg_seed\")\n\n## Import private functions from 'future'\nimport_future_functions <- function() {\n  .debug <<- import_future(\".debug\", mode = \"environment\", default = new.env(parent = emptyenv()))\n\n  ## future (>= 1.49.0)\n  sQuoteLabel <<- import_future(\"sQuoteLabel\")\n}\n"
  },
  {
    "path": "R/chunking.R",
    "content": "`chunkWith[[` <- function(x, subset) {\n  if (getOption(\"future.apply.chunkWith\", \"[[\") == \"[\") {\n    return(x[subset])\n  }\n  \n  ## Make sure to preserve behavior of S3 method-specific\n  ## `[[` subsetting like lapply() and mapply() does it\n  ny <- length(subset)\n  y <- vector(\"list\", length = ny)\n  names(y) <- names(x)[subset]\n  for (kk in seq_len(ny)) {\n    idx <- subset[kk]\n    value <- x[[idx]]\n    if (is.null(value)) {\n      y[kk] <- list(value)\n    } else {\n      y[[kk]] <- value\n    }\n  }\n  y\n}\n"
  },
  {
    "path": "R/condition-handlers.R",
    "content": "#' @importFrom future FutureInterruptError\nonInterrupt <- function(int, fcn_name, debug = FALSE) {\n  if (debug) {\n    mdebug_push(\"onInterrupt() ...\")\n    mdebug(sprintf(\"Received <%s>\", class(int)[1]))\n    on.exit(mdebug_pop())\n  }\n  \n  when <- Sys.time()\n  host <- Sys.info()[[\"nodename\"]]\n  pid <- Sys.getpid()\n  msg <- sprintf(\"%s() interrupted at %s, while running on %s (pid %s)\", fcn_name, format(when, format = \"%FT%T\"), sQuote(host), pid)\n\n  ## By signaling the interrupt as an error, the next handler, which should\n  ## be onError(), will take care of canceling outstanding futures\n  stop(FutureInterruptError(msg))\n}\n\n\n\n#' @importFrom future cancel resolve value\nonError <- function(ex, futures, debug = FALSE) {\n  if (debug) {\n    mdebug_push(\"onError() ...\")\n    mdebug(sprintf(\"Received <%s>\", class(ex)[1]))\n    on.exit(mdebug_pop())\n  }\n  \n  ## Canceling all futures\n  msg <- sprintf(\"Caught %s. Canceling all iterations ...\", class(ex)[1])\n  warning(msg, immediate. = TRUE, call. = FALSE)\n  futures <- cancel(futures)\n\n  ## Make sure all workers finish before continuing\n  futures <- resolve(futures)\n\n  ## Collect all results\n  for (f in futures) tryCatch(value(f), error = identity)\n\n  if (debug) mdebug(sprintf(\"Signaling: <%s>\", class(ex)[1]))\n\n  stop(ex)\n}\n"
  },
  {
    "path": "R/fold.R",
    "content": "#' Efficient Fold, Reduce, Accumulate, Combine of a Vector\n#'\n#' @param x A vector.\n#' \n#' @param f A binary function, i.e. a function take takes two arguments.\n#'\n#' @param left If `TRUE`, vector is combined from the left (the first element),\n#' otherwise the right (the last element).\n#'\n#' @param unname If `TRUE`, function `f` is called as\n#' \\code{f(unname(y), x[[ii]])}, otherwise as \\code{f(y, x[[ii]])},\n#' which may introduce name `\"y\"`.\n#'\n#' @param threshold An integer (>= 2) specifying the length where the\n#' recursive divide-and-conquer call will stop and incremental building of\n#' the partial value is performed.  Using `threshold = +Inf` will disable\n#' recursive folding.\n#'\n#' @return A vector.\n#' \n#' @details\n#' In order for recursive folding to give the same results as non-recursive\n#' folding, binary function `f` must be _associative_ with itself, i.e.\n#' \\code{f(f(x[[1]], x[[2]]), x[[3]])} equals\n#' \\code{f(x[[1]], f(x[[2]]), x[[3]])}.\n#'\n#' This function is a more efficient (memory and speed) of\n#' \\code{\\link[base:Reduce]{Reduce(f, x, right = !left, accumulate = FALSE)}},\n#' especially when `x` is long.\n#' \n#' @keywords internal\nfold <- function(x, f, left = TRUE, unname = TRUE, threshold = 1000L) {\n  f <- match.fun(f)\n  n <- length(x)\n  if (n == 0L) return(NULL)\n  if (!is.vector(x) || is.object(x)) x <- as.list(x)\n  if (n == 1L) return(x[[1]])\n  stop_if_not(length(left) == 1, is.logical(left), !is.na(left))\n  stop_if_not(length(threshold) == 1, is.numeric(threshold),\n              !is.na(threshold), threshold >= 2)\n\n  if (n >= threshold) {\n    ## Divide and conquer, i.e. split, build the two parts, and merge\n    n_mid <- n %/% 2\n    y_left  <- Recall(f = f, x = x[     1:n_mid], left = left,\n                      unname = unname, threshold = threshold)\n    y_right <- Recall(f = f, x = x[(n_mid+1L):n], left = left,\n                      unname = unname, threshold = threshold)\n    y <- f(y_left, y_right)\n    y_left <- y_right <- NULL\n  } else {\n    ## Incrementally build result vector\n    if (left) {\n      y <- x[[1L]]\n      if (unname) {\n        for (ii in 2:n)\n          y <- forceAndCall(n = 2L, FUN = f, unname(y), x[[ii]])\n      } else {\n        for (ii in 2:n)\n          y <- forceAndCall(n = 2L, FUN = f,         y, x[[ii]])\n      }\n    } else {\n      y <- x[[n]]\n      if (unname) {\n        for (ii in (n-1):1)\n          y <- forceAndCall(n = 2L, FUN = f, x[[ii]], unname(y))\n      } else {\n        for (ii in (n-1):1)\n          y <- forceAndCall(n = 2L, FUN = f, x[[ii]],         y)\n      }\n    }\n  }\n\n  y\n}\n"
  },
  {
    "path": "R/future.apply-package.R",
    "content": "#' future.apply: Apply Function to Elements in Parallel using Futures\n#'\n#' The \\pkg{future.apply} package provides parallel implementations of\n#' common \"apply\" functions provided by base \\R.  The parallel processing\n#' is performed via the \\pkg{future} ecosystem, which provides a large\n#' number of parallel backends, e.g. on the local machine, a remote cluster,\n#' and a high-performance compute cluster.\n#' \n#' Currently implemented functions are:\n#'\n#' * [future_apply()]: a parallel version of [apply()][base::apply]\n#' * [future_by()]: a parallel version of [by()][base::by]\n#' * [future_eapply()]: a parallel version of [eapply()][base::lapply]\n#' * [future_lapply()]: a parallel version of [lapply()][base::lapply]\n#' * [future_mapply()]: a parallel version of [mapply()][base::mapply]\n#' * [future_sapply()]: a parallel version of [sapply()][base::sapply]\n#' * [future_tapply()]: a parallel version of [tapply()][base::tapply]\n#' * [future_vapply()]: a parallel version of [vapply()][base::vapply]\n#' * [future_Map()]: a parallel version of [Map()][Map]\n#' * [future_replicate()]: a parallel version of [replicate()][base::replicate]\n#' * [future_.mapply()]: a parallel version of [.mapply()][base::.mapply]\n#'\n#' Reproducibility is part of the core design, which means that perfect,\n#' parallel random number generation (RNG) is supported regardless of the\n#' amount of chunking, type of load balancing, and future backend being used.\n#' \n#' Since these `future_*()` functions have the same arguments as the\n#' corresponding base \\R function, start using them is often as simple as\n#' renaming the function in the code.  For example, after attaching the package:\n#' ```r\n#' library(future.apply)\n#' ```\n#' code such as:\n#' ```r\n#' x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))\n#' y <- lapply(x, quantile, probs = 1:3/4)\n#' ```\n#' can be updated to:\n#' ```r\n#' y <- future_lapply(x, quantile, probs = 1:3/4)\n#' ```\n#'\n#' The default settings in the \\pkg{future} framework is to process code\n#' _sequentially_.  To run the above in parallel on the local machine\n#' (on any operating system), use:\n#' ```r\n#' plan(multisession)\n#' ```\n#' first.  That's it!\n#'\n#' To go back to sequential processing, use `plan(sequential)`.\n#' If you have access to multiple machines on your local network, use:\n#' ```r\n#' plan(cluster, workers = c(\"n1\", \"n2\", \"n2\", \"n3\"))\n#' ```\n#' This will set up four workers, one on `n1` and `n3`, and two on `n2`.\n#' If you have SSH access to some remote machines, use:\n#' ```r\n#' plan(cluster, workers = c(\"m1.myserver.org\", \"m2.myserver.org))\n#' ```\n#' See the \\pkg{future} package and [future::plan()] for more examples.\n#'\n#' The \\pkg{future.batchtools} package provides support for high-performance\n#' compute (HPC) cluster schedulers such as SGE, Slurm, and TORQUE / PBS.\n#' For example,\n#'\n#' * `plan(batchtools_slurm)`:\n#'      Process via a Slurm scheduler job queue.\n#' * `plan(batchtools_torque)`:\n#'      Process via a TORQUE / PBS scheduler job queue.\n#' \n#' This builds on top of the queuing framework that the \\pkg{batchtools}\n#' package provides. For more details on backend configuration, please see\n#' the \\pkg{future.batchtools} and \\pkg{batchtools} packages.\n#'\n#' These are just a few examples of parallel/distributed backend for the\n#' future ecosystem.  For more alternatives, see the 'Reverse dependencies'\n#' section on the\n#' [future CRAN package page](https://cran.r-project.org/package=future).\n#'\n#' @author\n#' Henrik Bengtsson, except for the implementations of `future_apply()`,\n#' `future_Map()`, `future_replicate()`, `future_sapply()`, and\n#' `future_tapply()`, which are adopted from the source code of the\n#' corresponding base \\R functions, which are licensed under GPL (>= 2)\n#' with 'The R Core Team' as the copyright holder.\n#' Because of these dependencies, the license of this package is GPL (>= 2).\n#' \n#' @keywords manip programming iteration\n#'\n#' @aliases future.apply-package\n#' @name future.apply\n\"_PACKAGE\"\n"
  },
  {
    "path": "R/future_Filter.R",
    "content": "#' @inheritParams future_mapply\n#' \n#' @param f A function of the arity \\eqn{k} if `future_Map()` is called with\n#' \\eqn{k} arguments. Unary for `future_Filter()`.\n#' \n#' @param x A vector-like object to iterate over.\n#' \n#' @return\n#' See [base::Filter()][Filter] for details.\n#'\n#' @example incl/future_Filter.R\n#'\n#' @author\n#' The implementation of `future_Filter()` is adopted from the source code\n#' of the corresponding base \\R function `Filter()`, which is licensed under\n#' GPL (>= 2) with 'The R Core Team' as the copyright holder.\n#' \n#' @rdname future_mapply\n#' @export\nfuture_Filter <- function(f, x, ...) {\n  f <- match.fun(f)\n  z <- unlist(future_lapply(x, f, ...))\n  if (is.null(z)) \n    return(x[integer()])\n  ind <- as.logical(z)\n  x[which(ind)]\n}\n"
  },
  {
    "path": "R/future_Map.R",
    "content": "#' @inheritParams future_mapply\n#' \n#' @param f A function of the arity \\eqn{k} if `future_Map()` is called with\n#' \\eqn{k} arguments. \n#' \n#' @return\n#' `future_Map()` is a simple wrapper to `future_mapply()` which does not\n#' attempt to simplify the result.\n#' See [base::Map()][Map] for details.\n#'\n#' @export\n#'\n#' @author\n#' The implementation of `future_Map()` is adopted from the source code\n#' of the corresponding base \\R function `Map()`, which is licensed under\n#' GPL (>= 2) with 'The R Core Team' as the copyright holder.\n#' \n#' @rdname future_mapply\nfuture_Map <- function(f, ..., future.envir = parent.frame(), future.label = \"future_Map-%d\") {\n  f <- match.fun(f)\n  future_mapply(FUN = f, ..., SIMPLIFY = FALSE, future.envir = future.envir, future.label = future.label)\n}\n"
  },
  {
    "path": "R/future_apply.R",
    "content": "#' Apply Functions Over Array Margins via Futures\n#'\n#' `future_apply()` implements [base::apply()] using future with perfect\n#' replication of results, regardless of future backend used.\n#' It returns a vector or array or list of values obtained by applying a\n#' function to margins of an array or matrix.\n#'\n#' @inheritParams future_lapply\n#' \n#' @param X an array, including a matrix.\n#' \n#' @param MARGIN A vector giving the subscripts which the function will be\n#' applied over. For example, for a matrix `1` indicates rows, `2` indicates\n#' columns, `c(1, 2)` indicates rows and columns.\n#' Where `X` has named dimnames, it can be a character vector selecting\n#' dimension names.\n#' \n#' @param \\ldots  (optional) Additional arguments passed to `FUN()`, except\n#' `future.*` arguments, which are passed on to [future_lapply()] used\n#' internally.\n#' \n#' @param simplify a logical indicating whether results should be simplified\n#' if possible.\n#'\n#' @return\n#' Returns a vector or array or list of values obtained by applying a\n#' function to margins of an array or matrix.\n#' See [base::apply()] for details.\n#'\n#' @author\n#' The implementation of `future_apply()` is adopted from the source code\n#' of the corresponding base \\R function, which is licensed under GPL (>= 2)\n#' with 'The R Core Team' as the copyright holder.\n#'\n#' @example incl/future_apply.R\n#'\n#' @importFrom future nbrOfWorkers\n#' @export\nfuture_apply <- function(X, MARGIN, FUN, ..., simplify = TRUE, future.envir = parent.frame(), future.stdout = TRUE, future.conditions = \"condition\", future.globals = TRUE, future.packages = NULL, future.seed = FALSE, future.scheduling = 1.0, future.chunk.size = NULL, future.label = \"future_apply-%d\") {\n    debug <- isTRUE(getOption(\"future.debug\"))\n    debug <- isTRUE(getOption(\"future.apply.debug\", debug))\n\n    FUN <- match.fun(FUN)\n    simplify <- isTRUE(simplify)\n\n    ## Ensure that X is an array object\n    dl <- length(dim(X))\n    if(!dl) stop(\"dim(X) must have a positive length\")\n    if(is.object(X))\n\tX <- if(dl == 2L) as.matrix(X) else as.array(X)\n    ## now record dim as coercion can change it\n    ## (e.g. when a data frame contains a matrix).\n    d <- dim(X)\n    dn <- dimnames(X)\n    ds <- seq_len(dl)\n\n    ## Extract the margins and associated dimnames\n\n    if (is.character(MARGIN)) {\n        if(is.null(dnn <- names(dn))) # names(NULL) is NULL\n           stop(\"'X' must have named dimnames\")\n        MARGIN <- match(MARGIN, dnn)\n        if (anyNA(MARGIN))\n            stop(\"not all elements of 'MARGIN' are names of dimensions\")\n    }\n    s.call <- ds[-MARGIN]\n    s.ans  <- ds[MARGIN]\n    d.call <- d[-MARGIN]\n    d.ans <- d[MARGIN]\n    dn.call <- dn[-MARGIN]\n    dn.ans <- dn[MARGIN]\n    ## dimnames(X) <- NULL\n\n    ## do the calls\n\n    d2 <- prod(d.ans)\n    if(d2 == 0L) {\n        ## arrays with some 0 extents: return ``empty result'' trying\n        ## to use proper mode and dimension:\n        ## The following is still a bit `hackish': use non-empty X\n        newX <- array(vector(typeof(X), 1L), dim = c(prod(d.call), 1L))\n        ans <- forceAndCall(1, FUN, if(length(d.call) < 2L) newX[,1] else\n                   array(newX[, 1L], d.call, dn.call), ...)\n        return(if(is.null(ans)) ans else if(length(d.ans) < 2L) ans[1L][-1L]\n               else array(ans, d.ans, dn.ans))\n    }\n\n\n  \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Support %globals%, %packages%, %seed%, ...\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    opts <- getOption(\"future.disposable\", NULL)\n    if (length(opts) > 0) {\n      for (name in names(opts)) {\n        var <- sprintf(\"future.%s\", name)\n        assign(var, opts[[name]], envir = environment(), inherits = FALSE)\n      }\n      if (!identical(attr(opts, \"dispose\"), FALSE)) {\n        options(future.disposable = NULL)\n      }\n    }\n\n\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Globals and Packages\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    gp <- getGlobalsAndPackagesXApply(\n      FUN,\n      args = list(X = X, ...),\n      envir = environment(),\n      future.globals = future.globals,\n      future.packages = future.packages,\n      debug = debug\n    )\n    globals <- gp$globals\n    packages <- gp$packages\n    gp <- NULL\n\n    ## Check size of global variables?\n    ## Doing it here, on the matrix object, is much faster than doing it for\n    ## the list elements passed to future_lapply()\n    oldMaxSize <- maxSize <- getOption(\"future.globals.maxSize\")\n    if (is.null(maxSize) || is.finite(maxSize)) {\n      if (is.null(maxSize)) maxSize <- 500 * 1024^2\n      objectSize <- import_future(\"objectSize\")\n      size <- objectSize(X)\n      nWorkers <- nbrOfWorkers()\n      chunk_size <- size / nWorkers\n      other_size <- attr(globals, \"total_size\")\n      ## Calculate size of the 'globals', if not already done\n      if (is.na(other_size)) other_size <- objectSize(X)\n      if (is.numeric(other_size)) chunk_size <- chunk_size + other_size\n      if (chunk_size > maxSize) {\n        asIEC <- import_future(\"asIEC\")\n        msg <- sprintf(\"The total size of %s (of class %s and type %s) is %s and the total size of the other argument is %s. With %d workers, this translates to %s per worker needed for future_apply(), which exceeds the maximum allowed size of %s (option 'future.globals.maxSize').\", sQuote(\"X\"), sQuote(class(X)[1]), sQuote(typeof(X)), asIEC(size), asIEC(other_size), nWorkers, asIEC(chunk_size), asIEC(maxSize))\n        if (debug) mdebug(msg)\n        stop(msg)\n      }\n      on.exit(options(future.globals.maxSize = oldMaxSize), add = TRUE)\n      options(future.globals.maxSize = +Inf)\n    }\n\n    newX <- aperm(X, c(s.call, s.ans))\n    dim(newX) <- c(prod(d.call), d2)\n\n    if(length(d.call) < 2L) {# vector\n        if (length(dn.call)) dimnames(newX) <- c(dn.call, list(NULL))\n        newX <- lapply(1L:d2, FUN = function(i) newX[,i])\n    } else\n        newX <- lapply(1L:d2, FUN = function(i)\n                       array(newX[,i], dim = d.call, dimnames = dn.call))\n\n    globals$...future.FUN <- NULL\n    ans <- future_lapply(\n      X = newX,\n      FUN = FUN,\n      ...,\n      future.envir = future.envir,\n      future.stdout = future.stdout,\n      future.conditions = future.conditions,\n      future.seed = future.seed,\n      future.scheduling = future.scheduling,\n      future.chunk.size = future.chunk.size,\n      future.globals = globals,\n      future.packages = packages,\n      future.label = future.label\n    )\n    \n    ## answer dims and dimnames\n\n    ans.list <- !simplify || is.recursive(ans[[1L]])\n    l.ans <- length(ans[[1L]])\n\n    ans.names <- names(ans[[1L]])\n    if(!ans.list)\n\tans.list <- any(lengths(ans) != l.ans)\n    if(!ans.list && length(ans.names)) {\n        all.same <- vapply(ans, function(x) identical(names(x), ans.names), NA)\n        if (!all(all.same)) ans.names <- NULL\n    }\n    len.a <- if(ans.list) d2 else length(ans <- unlist(ans, recursive = FALSE))\n    if(length(MARGIN) == 1L && len.a == d2) {\n\tnames(ans) <- if(length(dn.ans[[1L]])) dn.ans[[1L]] # else NULL\n\tans\n    }\n    else if(len.a == d2)\n\tarray(ans, d.ans, dn.ans)\n    else if(len.a && len.a %% d2 == 0L) {\n        if(is.null(dn.ans)) dn.ans <- vector(mode=\"list\", length(d.ans))\n\tdn1 <- list(ans.names)\n\tif(length(dn.call) && !is.null(n1 <- names(dn <- dn.call[1])) &&\n\t   nzchar(n1) && length(ans.names) == length(dn[[1]]))\n\t    names(dn1) <- n1\n\tdn.ans <- c(dn1, dn.ans)\n\tarray(ans, c(len.a %/% d2, d.ans),\n\t      if(!is.null(names(dn.ans)) || !all(vapply(dn.ans, is.null, NA)))\n\t\t  dn.ans)\n    } else\n\tans\n}\n"
  },
  {
    "path": "R/future_by.R",
    "content": "#' Apply a Function to a Data Frame Split by Factors via Futures\n#'\n#' @inheritParams future_lapply\n#' \n#' @param data An \\R object, normally a data frame, possibly a matrix.\n#' \n#' @param INDICES A factor or a list of factors, each of length `nrow(data)`.\n#'\n#' @param FUN a function to be applied to (usually data-frame) subsets of `data`.\n#'\n#' @param \\ldots Additional arguments pass to [future_lapply()] and\n#'   then to `FUN()`.\n#'\n#' @param simplify logical: see [base::tapply()].\n#' \n#' @return\n#' An object of class \"by\", giving the results for each subset.\n#' This is always a list if simplify is false, otherwise a list\n#' or array (see [base::tapply()]).\n#' See also [base::by()] for details.\n#'\n#' @example incl/future_by.R\n#'\n#' @details\n#' Internally, `data` is grouped by `INDICES` into a list of `data`\n#' subset elements which is then processed by [future_lapply()].\n#' When the groups differ significantly in size, the processing time\n#' may differ significantly between the groups.\n#' To correct for processing-time imbalances, adjust the amount of chunking\n#' via arguments `future.scheduling` and `future.chunk.size`.\n#'\n#' @section Note on 'stringsAsFactors':\n#' The `future_by()` is modeled as closely as possible to the\n#' behavior of `base::by()`.  Both functions have \"default\" S3 methods that\n#' calls `data <- as.data.frame(data)` internally.  This call may in turn call\n#' an S3 method for `as.data.frame()` that coerces strings to factors or not\n#' depending on whether it has a `stringsAsFactors` argument and what its\n#' default is.\n#' For example, the S3 method of `as.data.frame()` for lists changed its\n#' (effective) default from `stringsAsFactors = TRUE` to\n#' `stringsAsFactors = TRUE` in R 4.0.0.\n#' \n#'\n#' @rdname future_by\n#' @export\nfuture_by <- function(data, INDICES, FUN, ..., simplify = TRUE, future.envir = parent.frame()) {\n  future.envir <- force(future.envir)\n  UseMethod(\"future_by\")\n}\n\n\n#' @export\nfuture_by.default <- function(data, INDICES, FUN, ..., simplify = TRUE, future.envir = parent.frame()) {\n  ndim <- length(dim(data))\n  .SUBSETTER <- if (ndim == 0L) {\n     function(row) data[row, , drop = TRUE]\n  } else {\n     function(row) data[row, , drop = FALSE]\n  }\n\n  data <- as.data.frame(data)\n  future_by_internal(data = data, INDICES = INDICES, FUN = FUN, ...,\n                     simplify = simplify,\n\t\t     .INDICES.NAME = deparse(substitute(INDICES))[1L],\n\t\t     .CALL = match.call(),\n\t\t     .SUBSETTER = .SUBSETTER,\n                     future.envir = future.envir)\n}\n\n\n#' @export\nfuture_by.data.frame <- function(data, INDICES, FUN, ..., simplify = TRUE, future.envir = parent.frame()) {\n  if (inherits(INDICES, \"formula\"))\n    INDICES <- .formula2varlist(INDICES, data)\n    \n  future_by_internal(data = data, INDICES = INDICES, FUN = FUN, ...,\n                     simplify = simplify,\n\t\t     .INDICES.NAME = deparse(substitute(INDICES))[1L],\n\t\t     .CALL = match.call(),\n\t\t     .SUBSETTER = function(row) data[row, , drop = FALSE],\n                     future.envir = future.envir)\n}\n\n\n\nfuture_by_internal <- function(data, INDICES, FUN, ..., simplify = TRUE, .SUBSETTER, .CALL, .INDICES.NAME, future.envir = parent.frame(), future.label = \"future_by-%d\") {\n  fcn_name <- \"future_by_internal\"\n  \n  debug <- isTRUE(getOption(\"future.debug\"))\n  debug <- isTRUE(getOption(\"future.apply.debug\", debug))\n  if (debug) {\n    mdebugf_push(\"%s() ...\", fcn_name)\n    on.exit(mdebug_pop())\n  }\n\n  FUN <- future_by_match_FUN(FUN)  ## to be removed /HB 2022-10-24\n  stop_if_not(is.function(FUN))\n  stop_if_not(is.function(.SUBSETTER))\n\n  if (!is.list(INDICES)) {\n    INDEX <- vector(\"list\", length = 1L)\n    INDEX[[1L]] <- INDICES\n    names(INDEX) <- .INDICES.NAME\n    INDICES <- INDEX\n    INDEX <- NULL ## Not needed anymore\n  }\n\n  INDICES <- lapply(INDICES, FUN = as.factor)\n  nI <- length(INDICES)\n  if (!nI) stop(\"'INDICES' is of length zero\")\n\n  nd <- nrow(data)\n  if (!all(lengths(INDICES) == nd)) {\n    stop(\"All elements of argument 'INDICES' must have same length as 'data'\")\n  }\n\n  namelist <- lapply(INDICES, FUN = levels)\n  extent <- lengths(namelist, use.names = FALSE)\n  cumextent <- cumprod(extent)\n  if (cumextent[nI] > .Machine$integer.max) \n    stop(\"total number of levels >= 2^31\")\n\n  storage.mode(cumextent) <- \"integer\"\n  ngroup <- cumextent[nI]\n  group <- as.integer(INDICES[[1L]])\n  if (nI > 1L) {\n    for (i in 2L:nI) {\n      group <- group + cumextent[i - 1L] * (as.integer(INDICES[[i]]) - 1L)\n    }\n  }\n  cumextent <- NULL ## Not needed anymore\n  \n  levels(group) <- as.character(seq_len(ngroup))\n  class(group) <- \"factor\"\n  ans <- split(seq_len(nd), f = group)\n  names(ans) <- NULL\n  index <- as.logical(lengths(ans) > 0L)\n  group <- NULL ## Not needed anymore\n\n  grouped_data <- lapply(X = ans[index], FUN = .SUBSETTER)\n  ans <- future_lapply(X = grouped_data, FUN = FUN, ..., future.envir = future.envir, future.label = future.label)\n  grouped_data <- NULL  ## Not needed anymore\n\n  ansmat <- array({\n    if (simplify && all(lengths(ans) == 1L)) {\n      ans <- unlist(ans, recursive = FALSE, use.names = FALSE)\n      if (!is.null(ans) && is.atomic(ans)) vector(typeof(ans)) else NA\n    } else {\n      vector(\"list\", length = prod(extent))\n    }\n  }, dim = extent, dimnames = namelist)\n  \n  if (length(ans) > 0L) ansmat[index] <- ans\n  ans <- NULL ## Not needed anymore\n\n  structure(ansmat,\n    call = .CALL,\n    class = \"by\"\n  )\n}\n\n\nfuture_by_match_FUN <- function(FUN) {\n  if (is.function(FUN)) return(FUN)\n  \n  .Defunct(msg = \"Specifying the function 'FUN' for future_by() as a character string is defunct in future.apply (>= 1.12.0), because base::by() does not support it. Instead, specify it as a function, e.g. FUN = sqrt and FUN = `[[`\", package = .packageName)\n\n  match.fun(FUN)\n}\n"
  },
  {
    "path": "R/future_eapply.R",
    "content": "#' @inheritParams future_lapply\n#' \n#' @param env An \\R environment.\n#' \n#' @param all.names If `TRUE`, the function will also be applied to variables\n#' that start with a period (`.`), otherwise not.\n#' See [base::eapply()] for details.\n#'\n#' @return\n#' A named (unless `USE.NAMES = FALSE`) list.\n#' See [base::eapply()] for details.\n#'\n#' @rdname future_lapply\n#' @export\nfuture_eapply <- function(env, FUN, ..., all.names = FALSE, USE.NAMES = TRUE, future.envir = parent.frame(), future.label = \"future_eapply-%d\") {\n  FUN <- match.fun(FUN)\n  names <- ls(envir = env, all.names = all.names, sorted = FALSE)\n  X <- mget(names, envir = env, inherits = FALSE)\n  if (!USE.NAMES) names(X) <- NULL\n  future_lapply(X = X, FUN = FUN, ..., future.envir = future.envir, future.label = future.label)\n}\n"
  },
  {
    "path": "R/future_kernapply.R",
    "content": "#' Apply Smoothing Kernel in Parallel\n#'\n#' `future_kernapply()` is a futurized version of\n#' [stats::kernapply()], i.e. it computes, in parallel, the\n#' convolution between an input sequence and a specific kernel.\n#' Parallelization takes place over columns when `x` is a matrix,\n#' including a `ts` matrix.\n#'\n#' @inheritParams stats::kernapply\n#'\n#' @returns\n#' See [stats::kernapply()] for details.\n#'\n#' @examples\n#' library(datasets)\n#' library(stats)\n#'\n#' X <- EuStockMarkets[, 1:2]\n#' k <- kernel(\"daniell\", 50)  # a long moving average\n#' X_smooth <- future_kernapply(X, k = k)\n#'\n#' @export\nfuture_kernapply <- function(x, ...) {\n  UseMethod(\"future_kernapply\")\n}\n\n\n#' @rdname future_kernapply\n#'\n#' @importFrom stats kernapply\n#' @export\nfuture_kernapply.default <- function(x, k, circular = FALSE, ...) {\n  if (is.vector(x))\n    return(kernapply(x, k, circular = circular))\n  else if (is.matrix(x))\n    return(future_apply(x, MARGIN = 2, FUN = kernapply, k, circular = circular))\n  else\n    stop(\"'future_kernapply' is not available for object 'x'\")\n}\n\n\n#' @rdname future_kernapply\n#'\n#' @importFrom stats kernapply end frequency ts\n#' @export\nfuture_kernapply.ts <- function(x, k, circular = FALSE, ...) {\n  if (!is.matrix(x))\n    y <- kernapply(as.vector(x), k, circular = circular)\n  else\n    y <- future_apply(x, MARGIN = 2, FUN = kernapply, k, circular = circular)\n  ts(y, end = end(x), frequency = frequency(x))\n}\n"
  },
  {
    "path": "R/future_lapply.R",
    "content": "#' Apply a Function over a List or Vector via Futures\n#'\n#' `future_lapply()` implements [base::lapply()] using futures with perfect\n#' replication of results, regardless of future backend used.\n#' Analogously, this is true for all the other `future_nnn()` functions.\n#' \n#' @param X  A vector-like object to iterate over.\n#' \n#' @param FUN  A function taking at least one argument.\n#' \n#' @param \\ldots (optional) Additional arguments passed to `FUN()`.\n#' For `future_*apply()` functions and `replicate()`, any `future.*` arguments\n#' part of \\ldots are passed on to `future_lapply()` used internally.\n#' Importantly, if this is called inside another function which also declares\n#' \\ldots arguments, do not forget to explicitly pass such \\ldots arguments\n#' down to the `future_*apply()` function too, which will then pass them on\n#' to `FUN()`. See below for an example.\n#' \n#' @param future.envir An [environment] passed as argument `envir` to\n#'        [future::future()] as-is.\n#'\n#' @param future.stdout If `TRUE` (default), then the standard output of the\n#'        underlying futures is captured, and re-outputted as soon as possible.\n#'        If `FALSE`, any output is silenced (by sinking it to the null device\n#'        as it is outputted).\n#'        If `NA` (not recommended), output is _not_ intercepted.\n#'\n#' @param future.conditions A character string of conditions classes to be\n#'        captured and relayed.  The default is the same as the `condition`\n#'        argument of [future::Future()].\n#'        To not intercept conditions, use `conditions = character(0L)`.\n#'        Errors are always relayed.\n#'\n#' @param future.globals A logical, a character vector, or a named list for\n#'        controlling how globals are handled. For details, see below section.\n#'\n#' @param future.packages (optional) a character vector specifying packages\n#'        to be attached in the R environment evaluating the future.\n#' \n#' @param future.seed A logical or an integer (of length one or seven),\n#'        or a list of `length(X)` with pre-generated random seeds.\n#'        For details, see below section.\n#'  \n#' @param future.scheduling Average number of futures (\"chunks\") per worker.\n#'        If `0.0`, then a single future is used to process all elements\n#'        of `X`.\n#'        If `1.0` or `TRUE`, then one future per worker is used.\n#'        If `2.0`, then each worker will process two futures\n#'        (if there are enough elements in `X`).\n#'        If `Inf` or `FALSE`, then one future per element of\n#'        `X` is used.\n#'        Only used if `future.chunk.size` is `NULL`.\n#'\n#' @param future.chunk.size The average number of elements per future (\"chunk\").\n#'        If `Inf`, then all elements are processed in a single future.\n#'        If `NULL`, then argument `future.scheduling` is used.\n#' \n#' @param future.label If a character string, then each future is assigned\n#'        a label `sprintf(future.label, chunk_idx)`.  If TRUE, then the\n#'        same as `future.label = \"future_lapply-%d\"`.  If FALSE, no labels\n#'        are assigned.\n#'\n#' @return\n#' For `future_lapply()`, a list with same length and names as `X`.\n#' See [base::lapply()] for details.\n#'\n#' @section Global variables:\n#' Argument `future.globals` may be used to control how globals\n#' should be handled similarly to how the `globals` argument is used with\n#' `future()`.\n#' Since all function calls use the same set of globals, this function can do\n#' any gathering of globals upfront (once), which is more efficient than if\n#' it would be done for each future independently.\n#' If `TRUE` (default), then globals are automatically identified and gathered.\n#' If a character vector of names is specified, then those globals are gathered.\n#' If a named list, then those globals are used as is.\n#' In all cases, `FUN` and any \\ldots arguments are automatically\n#' passed as globals to each future created as they are always needed.\n#'\n#' @section Reproducible random number generation (RNG):\n#' Unless `future.seed` is `FALSE` or `NULL`, this function guarantees to\n#' generate the exact same sequence of random numbers _given the same initial\n#' seed / RNG state_ - this regardless of type of futures, scheduling\n#' (\"chunking\") strategy, and number of workers.\n#' \n#' RNG reproducibility is achieved by pregenerating the random seeds for all\n#' iterations (over `X`) by using parallel RNG streams.  In each\n#' iteration, these seeds are set before calling `FUN(X[[ii]], ...)`.\n#' _Note, for large `length(X)` this may introduce a large overhead._\n#'\n#' If `future.seed = TRUE`, then \\code{\\link[base:Random]{.Random.seed}}\n#' is used if it holds a parallel RNG seed, otherwise one is created\n#' randomly.\n#'\n#' If `future.seed = FALSE`, it is expected that none of the\n#' `FUN(X[[ii]], ...)` function calls use random number generation.\n#' If they do, then an informative warning or error is produced depending\n#' on settings. See [future::future()] for more details.\n#' Using `future.seed = NULL`, is like `future.seed = FALSE` but without\n#' the check whether random numbers were generated or not.\n#'\n#' As input, `future.seed` may also take a fixed initial seed (integer),\n#' either as a full parallel RNG seed, or as a seed generating such a\n#' full parallel seed. This seed will be used to generated `length(X)`\n#' parallel RNG streams.\n#'\n#' In addition to the above, it is possible to specify a pre-generated\n#' sequence of RNG seeds as a list such that\n#' `length(future.seed) == length(X)` and where each element is an\n#' integer seed vector that can be assigned to\n#' \\code{\\link[base:Random]{.Random.seed}}.  One approach to generate a\n#' set of valid RNG seeds based on fixed initial seed (here `42L`) is:\n#'\n#' ```r\n#' seeds <- future_lapply(seq_along(X), FUN = function(x) .Random.seed,\n#'                        future.chunk.size = Inf, future.seed = 42L)\n#' ```\n#'\n#' **Note that `as.list(seq_along(X))` is _not_ a valid set of such\n#' `.Random.seed` values.**\n#' \n#' In all cases but `future.seed = FALSE` and `NULL`, the RNG state of the\n#' calling R processes after this function returns is guaranteed to be\n#' \"forwarded one step\" from the RNG state that was before the call and\n#' in the same way regardless of `future.seed`, `future.scheduling`\n#' and future strategy used.  This is done in order to guarantee that an \\R\n#' script calling `future_lapply()` multiple times should be numerically\n#' reproducible given the same initial seed.\n#'\n#'\n#' @section Load balancing (\"chunking\"):\n#' Whether load balancing (\"chunking\") should take place or not can be\n#' controlled by specifying either argument\n#' `future.scheduling = <ratio>` or `future.chunk.size = <count>`.\n#'\n#' The value `future.chunk.size` specifies the average number of elements\n#' processed per future (\"chunks\").\n#' If `+Inf`, then all elements are processed in a single future (one worker).\n#' If `NULL`, then argument `future.scheduling` is used.\n#'\n#' The value `future.scheduling` specifies the average number of futures\n#' (\"chunks\") that each worker processes.\n#' If `0.0`, then a single future is used to process all iterations;\n#' none of the other workers are not used.\n#' If `1.0` or `TRUE`, then one future per worker is used.\n#' If `2.0`, then each worker will process two futures (if there are\n#' enough iterations).\n#' If `+Inf` or `FALSE`, then one future per iteration is used.\n#' The default value is `scheduling = 1.0`.\n#'\n#'\n#' @section Control processing order of elements:\n#' Attribute `ordering` of `future.chunk.size` or `future.scheduling` can\n#' be used to control the ordering the elements are iterated over, which\n#' only affects the processing order and _not_ the order values are returned.\n#' This attribute can take the following values:\n#' * index vector - a numeric vector of length `length(X)`\n#' * function     - a function taking one argument which is called as\n#'                  `ordering(length(X))` and which must return an\n#'                  index vector of length `length(X)`, e.g.\n#'                  `function(n) rev(seq_len(n))` for reverse ordering.\n#' * `\"random\"`   - this will randomize the ordering via random index\n#'                  vector `sample.int(length(X))`.\n#'\n#' For example, `future.scheduling = structure(TRUE, ordering = \"random\")`.\n#' _Note_, when elements are processed out of order, then captured standard\n#' output and conditions are relayed in that order as well.\n#'\n#' @example incl/future_lapply.R\n#'\n#' @keywords manip programming iteration\n#'\n#' @importFrom globals findGlobals\n#' @export\nfuture_lapply <- local({\n  tmpl_expr <- bquote_compile({\n    \"# future.apply::future_lapply(): process chunk of elements\"\n    lapply(seq_along(...future.elements_ii), FUN = function(jj) {\n       ...future.X_jj <- ...future.elements_ii[[jj]]\n       .(expr_FUN)\n    })\n  })\n\n  tmpl_expr_with_rng <- bquote_compile({\n    \"# future.apply::future_lapply(): process chunk of elements while setting random seeds\"\n    lapply(seq_along(...future.elements_ii), FUN = function(jj) {\n       ...future.X_jj <- ...future.elements_ii[[jj]]\n       assign(\".Random.seed\", ...future.seeds_ii[[jj]], envir = globalenv(), inherits = FALSE)\n       .(expr_FUN)\n    })\n  })\n\n  function(X, FUN, ..., future.envir = parent.frame(), future.stdout = TRUE, future.conditions = \"condition\", future.globals = TRUE, future.packages = NULL, future.seed = FALSE, future.scheduling = 1.0, future.chunk.size = NULL, future.label = \"future_lapply-%d\") {\n    fcn_name <- \"future_lapply\"\n    args_name <- \"X\"\n  \n    ## Coerce to as.list()?\n    if (!is.vector(X) || is.object(X)) X <- as.list(X)\n    \n    ## Nothing to do?\n    nX <- length(X)\n    if (nX == 0L) return(as.list(X))\n\n    FUN <- match.fun(FUN)\n\n    debug <- isTRUE(getOption(\"future.debug\"))\n    debug <- isTRUE(getOption(\"future.apply.debug\", debug))\n    if (debug) {\n      mdebugf_push(\"%s() ...\", fcn_name)\n      on.exit(mdebug_pop())\n    }\n  \n    ## NOTE TO SELF: We'd ideally have a 'future.envir' argument also for\n    ## this function, cf. future().  However, it's not yet clear to me how\n    ## to do this, because we need to have globalsOf() to search for globals\n    ## from the current environment in order to identify the globals of \n    ## arguments 'FUN' and '...'. /HB 2017-03-10\n    envir <- environment()\n    \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Future expression\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ...future.FUN <- NULL ## To please R CMD check\n  \n    ## Does FUN() rely on '...' being a global?\n    ## If so, make sure to *not* pass '...' to FUN() \n    globals_FUN <- findGlobals(FUN, dotdotdot = \"return\")\n    if (debug) {\n      mdebugf(\"Globals in FUN(): [n=%d] %s\", length(globals_FUN), commaq(globals_FUN))\n    }\n    global_dotdotdot <- (\"...\" %in% globals_FUN)\n    if (global_dotdotdot) {\n      ## Yes; don't pass '...' to FUN()\n      expr_FUN <- quote({\n        ...future.FUN(...future.X_jj)\n      })\n      if (debug) mdebugf(\"=> Will not pass '...' to FUN(): %s\", commaq(deparse(expr_FUN)))\n    } else {\n      ## No; okay to pass '...' to FUN()\n      expr_FUN <- quote({\n        ...future.FUN(...future.X_jj, ...)\n      })\n      if (debug) mdebugf(\"=> Will pass '...' to FUN(): %s\", commaq(deparse(expr_FUN)))\n    }\n    \n    ## With or without RNG?\n    expr <- bquote_apply(\n      if (is.null(future.seed) || isFALSE(future.seed) || isNA(future.seed)) {\n        tmpl_expr\n      } else {\n        tmpl_expr_with_rng\n      }\n    )\n  \n\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Process\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    values <- future_xapply(\n      FUN = FUN,\n      nX = nX,\n      chunk_args = X,\n      args = list(...),\n      get_chunk = `chunkWith[[`,\n      expr = expr,\n      envir = envir,\n      future.envir = future.envir,\n      future.globals = future.globals,\n      future.packages = future.packages,\n      future.scheduling = future.scheduling,\n      future.chunk.size = future.chunk.size,\n      future.stdout = future.stdout,\n      future.conditions = future.conditions,\n      future.seed = future.seed,\n      future.label = future.label,\n      fcn_name = fcn_name,\n      args_name = args_name,\n      debug = debug\n    )\n  \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Reduce\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    names(values) <- names(X)\n    \n    values\n  }\n})"
  },
  {
    "path": "R/future_mapply.R",
    "content": "#' Apply a Function to Multiple List or Vector Arguments\n#'\n#' `future_mapply()` implements [base::mapply()] using futures with perfect\n#' replication of results, regardless of future backend used.\n#' Analogously to `mapply()`, `future_mapply()` is a multivariate version of\n#' `future_sapply()`.\n#' It applies `FUN` to the first elements of each \\ldots argument,\n#' the second elements, the third elements, and so on.\n#' Arguments are recycled if necessary.\n#' \n#' @inheritParams future_lapply\n#' \n#' @param FUN  A function to apply, found via [base::match.fun()].\n#' \n#' @param \\ldots  Arguments to vectorize over, will be recycled to common\n#' length, or zero if one of them is of length zero.\n#'\n#' @param MoreArgs  A list of other arguments to `FUN`.\n#'\n#' @param SIMPLIFY  A logical or character string; attempt to reduce the\n#' result to a vector, matrix or higher dimensional array; see the simplify\n#' argument of [base::sapply()].\n#' \n#' @param USE.NAMES A logical; use names if the first \\ldots argument has\n#' names, or if it is a character vector, use that character vector as the\n#' names.\n#'\n#' @param future.globals A logical, a character vector, or a named list for\n#'        controlling how globals are handled.\n#'        For details, see [future_lapply()].\n#'\n#' @param future.seed A logical or an integer (of length one or seven), or\n#'        a list of `max(lengths(list(...)))` with pre-generated random seeds.\n#'        For details, see [future_lapply()].\n#'\n#' @return\n#' `future_mapply()` returns a list, or for `SIMPLIFY = TRUE`, a vector,\n#' array or list.  See [base::mapply()] for details.\n#'\n#' @example incl/future_mapply.R\n#'\n#' @keywords manip programming iteration\n#'\n#' @export\nfuture_mapply <- function(FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE, future.envir = parent.frame(), future.stdout = TRUE, future.conditions = \"condition\", future.globals = TRUE, future.packages = NULL, future.seed = FALSE, future.scheduling = 1.0, future.chunk.size = NULL, future.label = \"future_mapply-%d\") {\n  fcn_name <- \"future_mapply\"\n  args_name <- \"...\"\n  \n  FUN <- match.fun(FUN)\n\n  dots <- list(...)\n  \n  ## Nothing to do?\n  if (length(dots) == 0L) return(list())\n  \n  ns <- lengths(dots)\n  \n  ## Nothing to do?\n  ## \"max-or-0-if-any\" recycling rule was introduced in R (>= 4.2.0)\n  if (any(ns == 0L)) {\n    if (!USE.NAMES) return(list())\n    values <- list()\n    first <- dots[[1]]\n    names <- names(first)\n    if (length(names) > 0L) {\n      names <- character(0L)\n    } else if (is.null(names) && is.character(first)) {\n      names <- character(0L)\n    }\n    names(values) <- names\n    return(values)\n  }\n\n  stop_if_not(all(ns > 0L))\n  \n  ## Recycle?\n  nX <- max(ns)\n  stretch <- which(ns < nX)\n  if (length(stretch) > 0L) {\n    for (kk in stretch) dots[[kk]] <- rep(dots[[kk]], length.out = nX)\n    ns <- lengths(dots)\n  }\n  stop_if_not(all(ns == nX))\n  \n  stop_if_not(is.null(MoreArgs) || is.list(MoreArgs))\n\n  debug <- isTRUE(getOption(\"future.debug\"))\n  debug <- isTRUE(getOption(\"future.apply.debug\", debug))\n  if (debug) {\n    mdebugf_push(\"%s() ...\", fcn_name)\n    on.exit(mdebug_pop())\n  }\n\n  ## NOTE TO SELF: We'd ideally have a 'future.envir' argument also for\n  ## this function, cf. future().  However, it's not yet clear to me how\n  ## to do this, because we need to have globalsOf() to search for globals\n  ## from the current environment in order to identify the globals of \n  ## arguments 'FUN' and '...'. /HB 2017-03-10\n  envir <- future.envir\n  envir <- environment()\n\n\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  ## Support %globals%, %packages%, %seed%, ...\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  opts <- getOption(\"future.disposable\", NULL)\n  if (length(opts) > 0) {\n    for (name in names(opts)) {\n      var <- sprintf(\"future.%s\", name)\n      assign(var, opts[[name]], envir = environment(), inherits = FALSE)\n    }\n    if (!identical(attr(opts, \"dispose\"), FALSE)) {\n      options(future.disposable = NULL)\n    }\n  }\n\n\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  ## Future expression\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  ...future.FUN <- NULL ## To please R CMD check\n  \n  ## Set .Random.seed?\n  if (is.null(future.seed) || isFALSE(future.seed) || isNA(future.seed)) {\n     expr <- quote({\n       args <- c(list(FUN = ...future.FUN), ...future.elements_ii, MoreArgs = list(MoreArgs), SIMPLIFY = FALSE, USE.NAMES = FALSE)\n       do.call(mapply, args = args)\n     })\n  } else {\n    expr <- quote({\n      ...future.FUN2 <- function(..., ...future.seeds_ii_jj) {\n        assign(\".Random.seed\", ...future.seeds_ii_jj, envir = globalenv(), inherits = FALSE)\n        ...future.FUN(...)\n      }\n      args <- c(list(FUN = ...future.FUN2), ...future.elements_ii, list(...future.seeds_ii_jj = ...future.seeds_ii), MoreArgs = list(MoreArgs), SIMPLIFY = FALSE, USE.NAMES = FALSE)\n      do.call(mapply, args = args)\n    })\n  }\n\n\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  ## Process\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  values <- future_xapply(\n    FUN = FUN,\n    nX = nX,\n    chunk_args = dots,\n    MoreArgs = MoreArgs,\n    get_chunk = function(X, chunk) lapply(X, FUN = `chunkWith[[`, chunk),\n    expr = expr,\n    envir = envir,\n    future.envir = future.envir,\n    future.globals = future.globals,\n    future.packages = future.packages,\n    future.scheduling = future.scheduling,\n    future.chunk.size = future.chunk.size,\n    future.stdout = future.stdout,\n    future.conditions = future.conditions,\n    future.seed = future.seed,\n    future.label = future.label,\n    fcn_name = fcn_name,\n    args_name = args_name,\n    debug = debug\n  )\n\n\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  ## Reduce\n  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  if (USE.NAMES && length(dots) > 0L) {\n    if (is.null(names1 <- names(dots[[1L]])) && is.character(dots[[1L]])) {\n      names(values) <- dots[[1L]]\n    } else if (!is.null(names1)) {\n      names(values) <- names1\n    }\n  }\n\n  if (!isFALSE(SIMPLIFY) && length(values) > 0L) {\n    values <- simplify2array(values, higher = (SIMPLIFY == \"array\"))\n  } \n  \n  values\n}\n\n\n#' @param dots A list of arguments to vectorize over (vectors or lists of\n#' strictly positive length, or all of zero length).\n#'\n#' @return\n#' `future_.mapply()` returns a list. See [base::.mapply()] for details.\n#'\n#' @details\n#' Note that [base::.mapply()], which `future_.mapply()` is modeled after\n#' is listed as an \"internal\" function in \\R despite being exported.\n#'\n#' @rdname future_mapply\n#' @export\nfuture_.mapply <- function(FUN, dots, MoreArgs, ..., future.label = \"future_.mapply-%d\") {\n  args <- c(\n    list(FUN = FUN),\n    dots,\n    list(\n      MoreArgs = MoreArgs,\n      SIMPLIFY = FALSE,\n      USE.NAMES = FALSE,\n      ...,\n      future.label = future.label\n    )\n  )\n  do.call(future_mapply, args = args, envir = parent.frame())\n}\n"
  },
  {
    "path": "R/future_replicate.R",
    "content": "#' @inheritParams future_lapply\n#'\n#' @param n The number of replicates.\n#'\n#' @param expr An \\R expression to evaluate repeatedly.\n#' \n#' @return\n#' `future_replicate()` is a wrapper around `future_sapply()` and return\n#' simplified object according to the `simplify` argument.\n#' See [base::replicate()] for details.\n#' Since `future_replicate()` usually involves random number generation (RNG),\n#' it uses `future.seed = TRUE` by default in order produce sound random\n#' numbers regardless of future backend and number of background workers used.\n#'\n#' @export\n#'\n#' @rdname future_lapply\nfuture_replicate <- function(n, expr, simplify = \"array\",\n                             future.seed = TRUE, ...,\n                             future.envir = parent.frame(),\n                             future.label = \"future_replicate-%d\")\n  future_sapply(X = integer(n),\n                FUN = eval.parent(substitute(function(...)expr)),\n                simplify = simplify,\n                future.seed = future.seed,\n                ...,\n                future.envir = future.envir,\n                future.label = future.label)\n"
  },
  {
    "path": "R/future_sapply.R",
    "content": "#' @inheritParams future_lapply\n#' \n#' @param simplify See [base::sapply()] and [base::tapply()], respectively.\n#' \n#' @param USE.NAMES See [base::sapply()].\n#'\n#' @return\n#' For `future_sapply()`, a vector with same length and names as \\code{X}.\n#' See [base::sapply()] for details.\n#'\n#' @export\n#'\n#' @author\n#' The implementations of `future_replicate()`, `future_sapply()`, and\n#' `future_tapply()` are adopted from the source code of the corresponding\n#' base \\R functions, which are licensed under GPL (>= 2) with\n#' 'The R Core Team' as the copyright holder.\n#' \n#' @rdname future_lapply\nfuture_sapply <- function(X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE, future.envir = parent.frame(), future.label = \"future_sapply-%d\") {\n  FUN <- match.fun(FUN)\n  answer <- future_lapply(X = X, FUN = FUN, ..., future.envir = future.envir, future.label = future.label)\n  if (USE.NAMES && is.character(X) && is.null(names(answer)))\n    names(answer) <- X\n\n  if (!isFALSE(simplify) && length(answer))\n    simplify2array(answer, higher = (simplify == \"array\"))\n  else\n    answer\n}\n"
  },
  {
    "path": "R/future_tapply.R",
    "content": "#' @inheritParams future_lapply\n#'\n#' @param X An \\R object for which a \\code{\\link[base]{split}} method\n#' exists.  Typically vector-like, allowing subsetting with\n#' \\code{\\link[base]{[}}, or a data frame.\n#'  \n#' @param INDEX A list of one or more factors, each of same length as `X`.\n#' The elements are coerced to \\code{\\link[base]{factor}}s by\n#' \\code{\\link[base:as.factor]{as.factor()}}. Can also be a formula, which\n#' is useful if `X` is a data frame; see the `f` argument in\n#' \\code{\\link[base:split]{split()}} for interpretation.\n#' \n#' @param default See [base::tapply()].\n#' \n#' @return\n#' `future_tapply()` returns an array with mode `\"list\"`, unless\n#' `simplify = TRUE` (default) _and_ `FUN` returns a scalar, in which\n#' case the mode of the array is the same as the returned scalars.\n#' See [base::tapply()] for details.\n#' \n#' @rdname future_lapply\n#' @export\nfuture_tapply <- function(X, INDEX, FUN = NULL, ...,\n                          default = NA, simplify = TRUE,\n\t\t\t  future.envir = parent.frame(),\n                          future.label = \"future_tapply-%d\") {\n  FUN <- if (!is.null(FUN)) \n    match.fun(FUN)\n  if (inherits(INDEX, \"formula\")) {\n    if (!is.data.frame(X))\n      stop(\"'X' must be a data frame when 'INDEX' is a formula\")\n    INDEX <- .formula2varlist(INDEX, X)\n  }\n  if (!is.list(INDEX)) \n    INDEX <- list(INDEX)\n  INDEX <- lapply(INDEX, FUN = as.factor)\n  nI <- length(INDEX)\n  if (!nI)\n    stop(\"'INDEX' is of length zero\")\n  \n  if (!is.object(X) && !all(lengths(INDEX) == length(X))) \n    stop(\"arguments must have same length\")\n  \n  namelist <- lapply(INDEX, FUN = levels)\n  extent <- lengths(namelist, use.names = FALSE)\n  cumextent <- cumprod(extent)\n  if (cumextent[nI] > .Machine$integer.max) \n    stop(\"total number of levels >= 2^31\")\n  \n  storage.mode(cumextent) <- \"integer\"\n  ngroup <- cumextent[nI]\n  group <- as.integer(INDEX[[1L]])\n  if (nI > 1L) {\n    for (i in 2L:nI) {\n      group <- group + cumextent[i - 1L] * (as.integer(INDEX[[i]]) - 1L)\n    }\n  }\n  if (is.null(FUN)) return(group)\n  \n  levels(group) <- as.character(seq_len(ngroup))\n  class(group) <- \"factor\"\n  ans <- split(X, f = group)\n  names(ans) <- NULL\n  index <- as.logical(lengths(ans))\n  ans <- future_lapply(X = ans[index], FUN = FUN, ..., future.envir = future.envir, future.label = future.label)\n  \n  ansmat <- array({\n    if (simplify && all(lengths(ans) == 1L)) {\n      ans <- unlist(ans, recursive = FALSE, use.names = FALSE)\n      if (!is.null(ans) && is.na(default) && is.atomic(ans))\n        vector(typeof(ans))\n      else\n        default\n    } else {\n      vector(\"list\", prod(extent))\n    }\n  }, dim = extent, dimnames = namelist)\n  \n  if (length(ans) > 0L) ansmat[index] <- ans\n\n  ansmat\n}\n\n\n.formula2varlist <- import_base(\".formula2varlist\", default = local({\n  if (!exists(\"errorCondition\", mode = \"function\", envir = baseenv(), inherits = FALSE)) {\n    errorCondition <- function(message, ..., class = NULL, call = NULL) {\n      structure(\n        list(message = as.character(message), call = call, ...),\n        class = c(class, \"error\", \"condition\")\n      )\n    }\n  }\n  \n  function(...) {\n    stop(errorCondition(\"future_tapply(X, INDEX, ...), where 'INDEX' is a formula, requires R (>= 4.3.0\"), class = \"NotSupportedByThisRVersionError\")\n  }\n}))\n"
  },
  {
    "path": "R/future_vapply.R",
    "content": "#' @inheritParams future_lapply\n#' \n#' @param FUN.VALUE A template for the required return value from\n#' each `FUN(X[ii], ...)`.\n#' Types may be promoted to a higher type within the ordering\n#' logical < integer < double < complex, but not demoted.\n#' See [base::vapply()] for details.\n#'\n#' @return\n#' For `future_vapply()`, a vector with same length and names as \\code{X}.\n#' See [base::vapply()] for details.\n#'\n#' @export\n#'\n#' @rdname future_lapply\nfuture_vapply <- function(X, FUN, FUN.VALUE, ..., USE.NAMES = TRUE, future.envir = parent.frame(), future.label = \"future_vapply-%d\") {\n  ## Coerce to as.list()?\n  if (!is.vector(X) || is.object(X)) X <- as.list(X)\n  \n  n <- length(X)\n  FUN <- match.fun(FUN)\n  stop_if_not(is.function(FUN))\n  stop_if_not(is.vector(FUN.VALUE) || is.array(FUN.VALUE))\n  type <- typeof(FUN.VALUE)\n  times <- length(FUN.VALUE)\n  dim <- dim(FUN.VALUE)\n  stop_if_not(is.logical(USE.NAMES), length(USE.NAMES) == 1L, !is.na(USE.NAMES))\n\n  valid_types <- switch(\n    type,\n    logical =   \"logical\",\n    integer = c(\"logical\", \"integer\"),\n    double  = c(\"logical\", \"integer\", \"double\"),\n    complex = c(\"logical\", \"integer\", \"double\", \"complex\"),\n    type\n  )\n  \n  x_FUN <- FUN\n  res <- future_lapply(X, FUN = function(x, ...) {\n    value <- x_FUN(x, ...)\n    if (length(value) != times) {\n      stopf(\"values must be length %d, but FUN(X[[ii]]) result is length %d\",\n            times, length(value))\n    }\n    stop_if_not(all(dim(value) == dim), typeof(value) %in% valid_types)\n    value\n  }, ..., future.envir = future.envir, future.label = future.label)\n\n  if (!is.null(dim)) {\n    dim_res <- c(dim, n)\n  } else if (times != 1L) {\n    dim_res <- c(times, n)\n  } else {\n    dim_res <- NULL\n  }\n\n  if (USE.NAMES && length(res) > 0L) {\n    if (is.null(dim)) {\n      names_FUN.VALUE <- names(FUN.VALUE)\n      if (is.null(names_FUN.VALUE)) names_FUN.VALUE <- names(res[[1]])\n    } else {\n      names_FUN.VALUE <- dimnames(FUN.VALUE)\n      if (is.null(names_FUN.VALUE)) names_FUN.VALUE <- dimnames(res[[1]])\n    }\n  }\n  \n  res <- unlist(res, use.names = FALSE)\n  if (is.null(res)) res <- vector(mode = type, length = 0L)\n  if (!is.null(dim_res)) dim(res) <- dim_res\n  \n  if (USE.NAMES) {\n    if (is.array(res)) {\n      n_dim <- length(dim(res))\n      dimnames <- vector(\"list\", length = n_dim)\n      if (is.null(dim)) {\n        names <- names(X)\n        if (!is.null(names)) dimnames[[2]] <- names\n        names <- names_FUN.VALUE\n        if (!is.null(names)) dimnames[[1]] <- names\n      } else {\n        names <- names(X)\n        if (!is.null(names)) dimnames[[n_dim]] <- names\n        names <- names_FUN.VALUE\n        if (!is.null(names)) dimnames[-n_dim] <- names\n      }\n      if (!all(unlist(lapply(dimnames, FUN = is.null), use.names = FALSE))) {\n        dimnames(res) <- dimnames\n      }\n    } else {\n      names(res) <- names(X)\n    }\n  }\n  \n  res  \n}\n"
  },
  {
    "path": "R/future_xapply.R",
    "content": "#' @importFrom future cancel Future nbrOfWorkers future resolve value as.FutureGlobals getGlobalsAndPackages\nfuture_xapply <- local({\n  tmpl_expr_options <- bquote_compile({\n    \"# future.apply:::future_xapply(): preserve future option\"\n    ...future.globals.maxSize.org <- getOption(\"future.globals.maxSize\")\n    if (!identical(...future.globals.maxSize.org, ...future.globals.maxSize)) {\n      oopts <- options(future.globals.maxSize = ...future.globals.maxSize)\n      on.exit(options(oopts), add = TRUE)\n    }\n    .(expr)\n  })\n\n  function(FUN, nX, chunk_args, args = NULL, MoreArgs = NULL, expr, envir = parent.frame(), future.envir, future.globals, future.packages, future.scheduling, future.chunk.size, future.stdout, future.conditions, future.seed, future.label, get_chunk, fcn_name = \"future_xapply\", args_name, ..., debug) {\n    if (debug) {\n      mdebugf_push(\"%s() -> future_xapply() ...\", fcn_name)\n      on.exit(mdebug_pop())\n    }\n      \n    stop_if_not(is.function(FUN))\n    \n    stop_if_not(is.logical(future.stdout), length(future.stdout) == 1L)\n    \n    stop_if_not(length(future.scheduling) == 1L, !is.na(future.scheduling),\n              is.numeric(future.scheduling) || is.logical(future.scheduling))\n  \n    stop_if_not(length(future.label) == 1L, !is.na(future.label),\n                is.logical(future.label) || is.character(future.label))\n    \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Support %globals%, %packages%, %seed%, ...\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    opts <- getOption(\"future.disposable\", NULL)\n    if (length(opts) > 0) {\n      for (name in names(opts)) {\n        var <- sprintf(\"future.%s\", name)\n        assign(var, opts[[name]], envir = environment(), inherits = FALSE)\n      }\n      if (!identical(attr(opts, \"dispose\"), FALSE)) {\n        options(future.disposable = NULL)\n      }\n    }\n\n\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Reproducible RNG (for sequential and parallel processing)\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    seeds <- make_rng_seeds(nX, seed = future.seed)\n    \n    ## Future expression (with or without setting the RNG state) and\n    ## pass possibly tweaked 'future.seed' to future()\n    if (is.null(seeds)) {\n      stop_if_not(is.null(future.seed) || isFALSE(future.seed))\n    } else {\n      ## If RNG seeds are used (given or generated), make sure to reset\n      ## the RNG state afterward\n      oseed <- next_random_seed()\n      if (debug) mdebugf(\"Will set RNG state on exit: %s\", hpaste(oseed))\n      on.exit(set_random_seed(oseed))\n      ## As seed=FALSE but without the RNG check\n      future.seed <- NULL\n    }\n  \n  \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Load balancing (\"chunking\")\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    chunks <- makeChunks(nX,\n                         nbrOfWorkers = nbrOfWorkers(),\n                         future.scheduling = future.scheduling,\n                         future.chunk.size = future.chunk.size)\n    if (debug) mdebugf(\"Number of chunks: %d\", length(chunks))\n  \n    ## Process elements in a custom order?\n    ordering <- attr(chunks, \"ordering\")\n    if (!is.null(ordering)) {\n      if (debug) mdebugf(\"Index remapping (attribute 'ordering'): [n = %d] %s\", length(ordering), hpaste(ordering))\n      chunks <- lapply(chunks, FUN = function(idxs) .subset(ordering, idxs))\n    }\n    \n  \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Globals and Packages\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    gp <- getGlobalsAndPackagesXApply(FUN = FUN,\n                                      args = args,\n                                      MoreArgs = MoreArgs,\n                                      envir = envir,\n                                      future.globals = future.globals,\n                                      future.packages = future.packages,\n                                      debug = debug)\n  \n    packages <- gp$packages\n    globals <- gp$globals\n    scanForGlobals <- gp$scanForGlobals\n    gp <- NULL\n    \n    ## Add argument placeholders\n    globals_extra <- as.FutureGlobals(list(\n      ...future.elements_ii = NULL,\n      ...future.seeds_ii = NULL,\n      ...future.globals.maxSize = NULL\n    ))\n    attr(globals_extra, \"resolved\") <- TRUE\n    attr(globals_extra, \"total_size\") <- 0\n    globals <- c(globals, globals_extra)\n  \n    ## At this point a globals should be resolved and we should know their total size\n  ##  stop_if_not(attr(globals, \"resolved\"), !is.na(attr(globals, \"total_size\")))\n    if (debug) {\n      mdebugf(\"Globals pass to each chunk: [n=%d] %s\", length(globals), commaq(names(globals)))\n      mstr(globals)\n    }\n  \n    ## To please R CMD check\n    ...future.FUN <- ...future.elements_ii <- ...future.seeds_ii <-\n                     ...future.globals.maxSize <- NULL\n  \n    globals.maxSize <- getOption(\"future.globals.maxSize\")\n    globals.maxSize.default <- globals.maxSize\n    if (is.null(globals.maxSize.default)) globals.maxSize.default <- 500 * 1024^2\n\n    nchunks <- length(chunks)\n    if (debug) mdebugf(\"Number of futures (= number of chunks): %d\", nchunks)\n\n\n    ## Drop captured standard output and conditions as soon as they have\n    ## been relayed?\n    if (isTRUE(future.stdout)) {\n      future.stdout <- structure(future.stdout, drop = TRUE)\n    }\n    if (length(future.conditions) > 0) {\n      future.conditions <- structure(future.conditions, drop = TRUE)\n    }\n    \n  \n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    ## Futures\n    ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n    expr <- bquote_apply(tmpl_expr_options)\n  \n    ## Create labels?\n    if (isTRUE(future.label)) {\n      future.label <- sprintf(\"%s-%%d\", fcn_name)\n    }\n    if (is.character(future.label)) {\n      labels <- sprintf(future.label, seq_len(nchunks))\n      stopifnot(length(labels) == nchunks)\n    } else {\n      labels <- NULL\n    }\n  \n    if (debug) mdebugf(\"Launching %d futures (chunks) ...\", nchunks)\n    fs <- vector(\"list\", length = nchunks)\n    values <- tryCatch({\n      for (ii in seq_along(chunks)) {\n        chunk <- chunks[[ii]]\n        if (debug) mdebugf(\"Chunk #%d of %d ...\", ii, length(chunks))\n    \n        args_ii <- get_chunk(chunk_args, chunk)\n        globals_ii <- globals\n        ## Subsetting outside future is more efficient\n        globals_ii[[\"...future.elements_ii\"]] <- args_ii\n        packages_ii <- packages\n    \n        if (scanForGlobals) {\n          if (debug) mdebugf(\" - Finding globals in '%s' for chunk #%d ...\", args_name, ii)\n          gp <- getGlobalsAndPackages(args_ii, envir = envir, globals = TRUE)\n          globals_args <- gp$globals\n          packages_args <- gp$packages\n          gp <- NULL\n          \n          if (debug) {\n            mdebugf(\"   + additional globals found: [n=%d] %s\",\n                    length(globals_args), commaq(names(globals_args)))\n            mdebugf(\"   + additional namespaces needed: [n=%d] %s\",\n                    length(packages_args), commaq(packages_args))\n          }\n        \n          ## Export also globals found in arguments?\n          if (length(globals_args) > 0L) {\n            reserved <- intersect(c(\"...future.FUN\", \"...future.elements_ii\",\n                                    \"...future.seeds_ii\"), names(globals_args))\n            if (length(reserved) > 0) {\n              stop(\"Detected globals in '%s' using reserved variables names: \",\n                   args_name, commaq(reserved))\n            }\n            globals_args <- as.FutureGlobals(globals_args)\n            globals_ii <- unique(c(globals_ii, globals_args))\n    \n            ## Packages needed due to globals in arguments?\n            if (length(packages_args) > 0L)\n              packages_ii <- unique(c(packages_ii, packages_args))\n          }\n          \n          if (debug) mdebugf(\" - Finding globals in '%s' for chunk #%d ... DONE\", args_name, ii)\n        }\n        \n        args_ii <- NULL    \n    ##    stop_if_not(attr(globals_ii, \"resolved\"))\n  \n        if (!is.null(globals.maxSize)) {\n          globals_ii[\"...future.globals.maxSize\"] <- list(globals.maxSize)\n        }\n  \n        ## Adjust option 'future.globals.maxSize' to account for the fact that more\n        ## than one element is processed per future.  The adjustment is done by\n        ## scaling up the limit by the number of elements in the chunk.  This is\n        ## a \"good enough\" approach.\n        ## (https://github.com/futureverse/future.apply/issues/8).\n        if (length(chunks) > 1L) {\n          options(future.globals.maxSize = length(chunks) * globals.maxSize.default)\n          if (debug) mdebugf(\" - Adjusted option 'future.globals.maxSize': %.0f -> %d * %.0f = %.0f (bytes)\", globals.maxSize.default, length(chunks), globals.maxSize.default, getOption(\"future.globals.maxSize\"))\n          on.exit(options(future.globals.maxSize = globals.maxSize), add = TRUE)\n        }\n        \n        ## Using RNG seeds or not?\n        if (is.null(seeds)) {\n          if (debug) mdebug(\" - seeds: <none>\")\n        } else {\n          if (debug) mdebugf(\" - seeds: [%d] <seeds>\", length(chunk))\n          globals_ii[[\"...future.seeds_ii\"]] <- seeds[chunk]\n        }\n  \n        if (debug) {\n          mdebugf(\" - All globals exported: [n=%d] %s\",\n                  length(globals_ii), commaq(names(globals_ii)))\n        }\n\n        ## FIXME: Handle interrupts also here, i.e. as soon as we have\n        ## launched the first future, we should be able to interrupt it\n        fs[[ii]] <- future(\n          expr, substitute = FALSE,\n          envir = future.envir,\n          stdout = future.stdout,\n          conditions = future.conditions,\n          globals = globals_ii, packages = packages_ii,\n          seed = future.seed,\n          label = labels[ii]\n        )\n        \n        if (debug) {\n          mdebug(\"Created future:\")\n          mprint(fs[[ii]])\n        }\n        \n        ## Not needed anymore\n        rm(list = c(\"chunk\", \"globals_ii\"))\n    \n        if (debug) mdebugf(\"Chunk #%d of %d ... DONE\", ii, nchunks)\n      } ## for (ii ...)\n      if (debug) mdebugf(\"Launching %d futures (chunks) ... DONE\", nchunks)\n    \n      ## 4. Resolving futures\n      if (debug) mdebugf(\"Resolving %d futures (chunks) ...\", nchunks)\n    \n      ## Check for RngFutureCondition:s when resolving futures?\n      if (isFALSE(future.seed)) {\n        withCallingHandlers({\n          values <- local({\n            oopts <- options(future.rng.onMisuse.keepFuture = FALSE)\n            on.exit(options(oopts))\n            value(fs)\n          })\n        }, RngFutureCondition = function(cond) {\n          ## One of \"our\" futures?\n          idx <- NULL\n          \n          ## Compare future UUIDs or whole futures?\n          uuid <- attr(cond, \"uuid\")\n          if (!is.null(uuid)) {\n            ## (a) Future UUIDs are available\n            for (kk in seq_along(fs)) {\n              if (identical(fs[[kk]]$uuid, uuid)) idx <- kk\n            }\n          } else {        \n            ## (b) Future UUIDs are not available, use Future object?\n            f <- attr(cond, \"future\")\n            if (is.null(f)) return()\n            ## Nothing to do?\n            if (!isFALSE(f$seed)) return()  ## shouldn't really happen\n            for (kk in seq_along(fs)) {\n              if (identical(fs[[kk]], f)) idx <- kk\n            }\n          }\n          \n          ## Nothing more to do, i.e. not one of our futures?\n          if (is.null(idx)) return()\n          \n          ## Adjust message to give instructions relevant to this package\n          f <- fs[[idx]]\n          label <- sQuoteLabel(f)\n          message <- sprintf(\"UNRELIABLE VALUE: One of the %s iterations (%s) unexpectedly generated random numbers without declaring so. There is a risk that those random numbers are not statistically sound and the overall results might be invalid. To fix this, specify 'future.seed=TRUE'. This ensures that proper, parallel-safe random numbers are produced via a parallel RNG method. To disable this check, use 'future.seed = NULL', or set option 'future.rng.onMisuse' to \\\"ignore\\\".\", sQuote(.packageName), label)\n          cond$message <- message\n          if (inherits(cond, \"warning\")) {\n            warning(cond)\n            invokeRestart(\"muffleWarning\")\n          } else if (inherits(cond, \"error\")) {\n            stop(cond)\n          }\n        }) ## withCallingHandlers()\n      } else {\n        ## value() exits early if it detects a future with an error.\n        ## In future (>= 1.40.0), non-resolved futures will be automatically\n        ## canceled if there's an error.\n        value(fs)\n      }\n    }, interrupt = function(int) {\n      onInterrupt(int, fcn_name = fcn_name, debug = debug)\n    }, error = function(e) {\n      onError(e, futures = fs, debug = debug)\n    }) ## tryCatch()\n\n    ## Not needed anymore\n    rm(list = \"fs\")\n  \n    if (debug) {\n      mdebugf(\" - Number of value chunks collected: %d\", length(values))\n      mdebugf(\"Resolving %d futures (chunks) ... DONE\", nchunks)\n    }\n  \n    ## Sanity check\n    stop_if_not(length(values) == nchunks)\n    \n    if (debug) mdebugf(\"Reducing values from %d chunks ...\", nchunks)\n  \n    values2 <- do.call(c, args = values)\n    \n    if (debug) {\n      mdebugf(\" - Number of values collected after concatenation: %d\",\n             length(values2))\n      mdebugf(\" - Number of values expected: %d\", nX)\n    }\n  \n    assert_values2(nX, values, values2, fcn_name = fcn_name, debug = debug)\n    values <- values2\n    rm(list = \"values2\")\n    \n    ## Sanity check (this may happen if the future backend is broken)\n    stop_if_not(length(values) == nX)\n  \n    ## Were elements processed in a custom order?\n    if (length(values) > 1L && !is.null(ordering)) {\n      invOrdering <- vector(mode(ordering), length = nX)\n      idx <- 1:nX\n      invOrdering[.subset(ordering, idx)] <- idx\n      rm(list = c(\"ordering\", \"idx\"))\n      if (debug) mdebugf(\"Reverse index remapping (attribute 'ordering'): [n = %d] %s\", length(invOrdering), hpaste(invOrdering))\n      values <- .subset(values, invOrdering)\n      rm(list = c(\"invOrdering\"))\n    }\n  \n    if (debug) mdebugf(\"Reducing values from %d chunks ... DONE\", nchunks)\n\n    values\n  } ## future_xapply()\n})\n"
  },
  {
    "path": "R/globals.R",
    "content": "#' @importFrom globals globalsByName\n#' @importFrom future as.FutureGlobals getGlobalsAndPackages resolve\ngetGlobalsAndPackagesXApply <- function(FUN, args = NULL, MoreArgs = NULL, envir, future.globals = TRUE, future.packages = NULL, debug = NA) {\n  use_args <- !is.null(args)\n  \n  if (is.na(debug)) {\n    debug <- isTRUE(getOption(\"future.debug\"))\n    debug <- isTRUE(getOption(\"future.apply.debug\", debug))\n  }\n  if (debug) {\n    mdebug_push(\"getGlobalsAndPackagesXApply() ...\")\n    on.exit(mdebug_pop())\n  }\n\n  packages <- NULL\n  globals <- future.globals\n  scanForGlobals <- FALSE\n  if (is.logical(globals)) {\n    if (debug) mdebugf(\"future.globals: %s\", globals)\n    ## Gather all globals?\n    if (globals) {\n      scanForGlobals <- TRUE\n      expr <- do.call(call, args = c(list(\"FUN\"),\n                                     if (use_args) args else MoreArgs))\n    } else {\n      expr <- NULL\n      attr(globals, \"add\") <- c(attr(globals, \"add\"),\n                                c(\"FUN\", if (use_args) \"...\" else \"MoreArgs\"))\n    }\n    gp <- getGlobalsAndPackages(expr, envir = envir, globals = globals)\n    globals <- gp$globals\n    packages <- gp$packages\n    gp <- NULL\n      \n    if (debug) {\n      mdebugf(\"globals found/used: [n=%d] %s\", length(globals), commaq(names(globals)))\n      mdebugf(\"needed namespaces: [n=%d] %s\", length(packages), commaq(packages))\n    }\n  } else if (is.character(globals)) {\n    if (debug) mdebugf(\"future.globals: %s\", commaq(globals))\n    globals <- unique(c(globals, \"FUN\", if (use_args) \"...\" else \"MoreArgs\"))\n    globals <- globalsByName(globals, envir = envir, mustExist = FALSE)\n  } else if (is.list(globals)) {\n    names <- names(globals)\n    if (debug) mdebugf(\"future.globals: <name-value list> with names %s\", commaq(names(globals)))\n    if (length(globals) > 0 && is.null(names)) {\n      stop(\"Invalid argument 'future.globals'. All globals must be named\")\n    }\n  } else {\n    stop(\"Invalid argument 'future.globals': \", mode(globals))\n  }\n  globals <- as.FutureGlobals(globals)\n  stop_if_not(inherits(globals, \"FutureGlobals\"))\n  \n  names <- names(globals)\n  if (!is.element(\"FUN\", names)) {\n    globals <- c(globals, FUN = FUN)\n  }\n  \n  if (use_args) {\n    if (debug) mdebug(\"use_args: TRUE\")\n    if (!is.element(\"...\", names)) {\n      if (debug) mdebug_push(\"Getting '...' globals ...\")\n      dotdotdot <- globalsByName(\"...\", envir = envir, mustExist = TRUE)\n      dotdotdot <- as.FutureGlobals(dotdotdot)\n      dotdotdot <- resolve(dotdotdot)\n      if (debug) {\n        mdebugf(\"'...' content: [n=%d] %s\", length(dotdotdot[[1]]), commaq(names(dotdotdot[[1]])))\n        mstr(dotdotdot)\n      }\n\n      ## Recalculate the total size?\n      maxSize <- getOption(\"future.globals.maxSize\")\n      if (is.null(maxSize) || is.finite(maxSize)) {\n        objectSize <- import_future(\"objectSize\")\n        attr(dotdotdot, \"total_size\") <- objectSize(dotdotdot)\n      }\n      \n      if (debug) mdebug_pop()\n      globals <- c(globals, dotdotdot)\n    }\n  } else if (!is.element(\"MoreArgs\", names)) {\n    globals <- c(globals, list(MoreArgs = MoreArgs))\n  }\n\n  ## Assert there are no reserved variables names among globals\n  reserved <- intersect(c(\"...future.FUN\", \"...future.elements_ii\",\n                        \"...future.seeds_ii\"), names)\n  if (length(reserved) > 0) {\n    stop(\"Detected globals using reserved variables names: \",\n         commaq(reserved))\n  }\n \n  ## Avoid FUN() clash with mapply(..., FUN) below.\n  names <- names(globals)\n  names[names == \"FUN\"] <- \"...future.FUN\"\n  names(globals) <- names\n  \n  if (debug) {\n    mdebugf(\"Globals to be used in all futures (chunks): [n=%d] %s\", length(globals), commaq(names(globals)))\n    mstr(globals)\n  }\n\n  if (!is.null(future.packages)) {\n    stop_if_not(is.character(future.packages))\n    future.packages <- unique(future.packages)\n    stop_if_not(!anyNA(future.packages), all(nzchar(future.packages)))\n    packages <- unique(c(packages, future.packages))\n  }\n  \n  if (debug) {\n    mdebugf(\"Packages to be attached in all futures: [n=%d] %s\", length(packages), commaq(packages))\n  }\n\n  list(globals = globals, packages = packages, scanForGlobals = scanForGlobals)\n} ## findGlobalsStep1()\n"
  },
  {
    "path": "R/makeChunks.R",
    "content": "#' Create Chunks of Index Vectors\n#'\n#' _This is an internal function._\n#' \n#' @param nbrOfElements (integer) Total number of elements to iterate over.\n#' \n#' @param nbrOfWorkers (integer) Number of workers available.\n#' \n#' @param future.scheduling (numeric) A strictly positive scalar.\n#' Only used if argument `future.chunk.size` is `NULL`.\n#'\n#' @param future.chunk.size (numeric) The maximum number of elements per\n#' chunk, or `NULL`.  If `NULL`, then the chunk sizes are given by the\n#' `future.scheduling` argument.\n#'\n#' @return A list of chunks, where each chunk is an integer vector of\n#' unique indices \\code{[1, nbrOfElements]}.  The union of all chunks\n#' holds `nbrOfElements` elements and equals `1:nbrOfElements`.\n#' If `nbrOfElements == 0`, then an empty list is returned.\n#'\n#' @section Control processing order of elements:\n#' Attribute `ordering` of `future.chunk.size` or `future.scheduling` can\n#' be used to control the ordering the elements are iterated over, which\n#' only affects the processing order _not_ the order values are returned.\n#' This attribute can take the following values:\n#' * index vector - a numeric vector of length `nbrOfElements` specifying\n#'                  how elements are remapped\n#' * function     - a function taking one argument which is called as\n#'                  `ordering(nbrOfElements)` and which must return an\n#'                  index vector of length `nbrOfElements`, e.g.\n#'                  `function(n) rev(seq_len(n))` for reverse ordering.\n#' * `\"random\"`   - this will randomize the ordering via random index\n#'                  vector `sample.int(nbrOfElements)`.\n#' \n#' @importFrom parallel splitIndices\n#' @keywords internal\nmakeChunks <- function(nbrOfElements, nbrOfWorkers,\n                       future.scheduling = 1.0, future.chunk.size = NULL) {\n  stop_if_not(nbrOfElements >= 0L, nbrOfWorkers >= 1L)\n\n  ## 'future.chunk.size != NULL' takes precedence over 'future.scheduling'\n  if (!is.null(future.chunk.size)) {\n    stop_if_not(length(future.chunk.size) == 1L, !is.na(future.chunk.size),\n                future.chunk.size > 0)\n    ## Same definition as parallel:::staticNChunks() in R (>= 3.5.0)\n    nbrOfChunks <- max(1, ceiling(nbrOfElements / future.chunk.size))\n\n    ## Customized ordering?\n    ordering <- attr(future.chunk.size, \"ordering\", exact = TRUE)\n  } else {\n    if (is.logical(future.scheduling)) {\n      stop_if_not(length(future.scheduling) == 1L, !is.na(future.scheduling))\n      if (future.scheduling) {\n        nbrOfChunks <- nbrOfWorkers\n        if (nbrOfChunks > nbrOfElements) nbrOfChunks <- nbrOfElements\n      } else {\n        nbrOfChunks <- nbrOfElements\n      }\n    } else {\n      ## Treat 'future.scheduling' as the number of chunks per worker, i.e.\n      ## the number of chunks each worker should process on average.\n      stop_if_not(length(future.scheduling) == 1L, !is.na(future.scheduling),\n                  future.scheduling >= 0)\n      if (nbrOfWorkers > nbrOfElements) nbrOfWorkers <- nbrOfElements\n      nbrOfChunks <- future.scheduling * nbrOfWorkers\n      if (nbrOfChunks < 1L) {\n        nbrOfChunks <- 1L\n      } else if (nbrOfChunks > nbrOfElements) {\n        nbrOfChunks <- nbrOfElements\n      }\n    }\n    \n    ## Customized ordering?\n    ordering <- attr(future.scheduling, \"ordering\", exact = TRUE)\n  }\n\n  chunks <- splitIndices(nbrOfElements, ncl = nbrOfChunks)\n  \n  ## Customized ordering?\n  if (nbrOfElements > 1L && !is.null(ordering)) {\n    if (is.character(ordering) && ordering == \"random\") {\n      map <- stealth_sample.int(nbrOfElements)\n    } else if (is.numeric(ordering)) {\n      map <- ordering\n    } else if (is.function(ordering)) {\n      map <- ordering(nbrOfElements)\n    } else {\n      stopf(\"Unknown value of attribute %s for argument %s: %s\", \"ordering\", if (!is.null(future.chunk.size)) \"future.chunk.size\" else \"future.scheduling\", mode(ordering))\n    }\n\n    if (!is.null(map)) {\n      ## Simple validity check of \"ordering\".  Looking for NAs, range,\n      ## uniqueness is too expensive so skipped.\n      stop_if_not(length(map) == nbrOfElements)\n      attr(chunks, \"ordering\") <- map\n    }\n  }\n  \n  chunks\n}\n"
  },
  {
    "path": "R/options.R",
    "content": "#' Options used for future.apply\n#'\n#' Below are the \\R options and environment variables that are used by the\n#' \\pkg{future.apply} package and packages enhancing it.\\cr\n#' \\cr\n#' _WARNING: Note that the names and the default values of these options may\n#'  change in future versions of the package.  Please use with care until\n#'  further notice._\n#'\n#' For settings specific to the \\pkg{future} package, see\n#' [future::future.options] page.\n#'\n#' @section Options for debugging future.apply:\n#' \\describe{\n#'  \\item{\\option{future.apply.debug}:}{(logical) If `TRUE`, extensive debug messages are generated. (Default: `FALSE`)}\n#' }\n#'\n#'\n#' @section Environment variables that set R options:\n#' All of the above \\R \\option{future.apply.*} options can be set by\n#' corresponding environment variable \\env{R_FUTURE_APPLY_*} _when the\n#' \\pkg{future.apply} package is loaded_.\n#' For example, if `R_FUTURE_APPLY_DEBUG=TRUE`, then option\n#' \\option{future.apply.debug} is set to `TRUE` (logical).\n#'\n#' @examples\n#' \\dontrun{\n#' options(future.apply.debug = TRUE)\n#' }\n#'\n#' @seealso\n#' To set \\R options or environment variables when \\R starts (even before the \\pkg{future} package is loaded), see the \\link[base]{Startup} help page.  The \\href{https://cran.r-project.org/package=startup}{\\pkg{startup}} package provides a friendly mechanism for configuring \\R's startup process.\n#'\n#' @aliases\n#' future.apply.debug\n#' R_FUTURE_APPLY_DEBUG\n#'\n#' @name future.apply.options\nNULL\n\n\n\n\n# Set an R option from an environment variable\nupdate_package_option <- function(name, mode = \"character\", default = NULL, split = NULL, trim = TRUE, disallow = c(\"NA\"), force = FALSE, debug = FALSE) {\n  ## Nothing to do?\n  value <- getOption(name, NULL)\n  if (!force && !is.null(value)) return(getOption(name, default = default))\n\n  ## name=\"future.plan.disallow\" => env=\"R_FUTURE_PLAN_DISALLOW\"\n  env <- gsub(\".\", \"_\", toupper(name), fixed = TRUE)\n  env <- paste(\"R_\", env, sep = \"\")\n\n  env_value <- value <- Sys.getenv(env, unset = NA_character_)\n  ## Nothing to do?\n  if (is.na(value)) {  \n    if (debug) mdebugf(\"Environment variable %s not set\", sQuote(env))\n    return(getOption(name, default = default))\n  }\n  \n  if (debug) mdebugf(\"%s=%s\", env, sQuote(value))\n\n  ## Trim?\n  if (trim) value <- trim(value)\n\n  ## Nothing to do?\n  if (!nzchar(value)) return(getOption(name, default = default))\n\n  ## Split?\n  if (!is.null(split)) {\n    value <- strsplit(value, split = split, fixed = TRUE)\n    value <- unlist(value, use.names = FALSE)\n    if (trim) value <- trim(value)\n  }\n\n  ## Coerce?\n  mode0 <- storage.mode(value)\n  if (mode0 != mode) {\n    suppressWarnings({\n      storage.mode(value) <- mode\n    })\n    if (debug) {\n      mdebugf(\"Coercing from %s to %s: %s\", mode0, mode, commaq(value))\n    }\n  }\n\n  if (length(disallow) > 0) {\n    if (\"NA\" %in% disallow) {\n      if (any(is.na(value))) {\n        stopf(\"Coercing environment variable %s=%s to %s would result in missing values for option %s: %s\", sQuote(env), sQuote(env_value), sQuote(mode), sQuote(name), commaq(value))\n      }\n    }\n    if (is.numeric(value)) {\n      if (\"non-positive\" %in% disallow) {\n        if (any(value <= 0, na.rm = TRUE)) {\n          stopf(\"Environment variable %s=%s specifies a non-positive value for option %s: %s\", sQuote(env), sQuote(env_value), sQuote(name), commaq(value))\n        }\n      }\n      if (\"negative\" %in% disallow) {\n        if (any(value < 0, na.rm = TRUE)) {\n          stopf(\"Environment variable %s=%s specifies a negative value for option %s: %s\", sQuote(env), sQuote(env_value), sQuote(name), commaq(value))\n        }\n      }\n    }\n  }\n  \n  if (debug) {\n    mdebugf(\"=> options(%s = %s) [n=%d, mode=%s]\",\n            dQuote(name), commaq(value),\n            length(value), storage.mode(value))\n  }\n\n  do.call(options, args = structure(list(value), names = name))\n  \n  getOption(name, default = default)\n}\n\n\n## Set future options based on environment variables\nupdate_package_options <- function(debug = FALSE) {\n  update_package_option(\"future.apply.chunkWith\", default = \"[[\", debug = debug)\n}\n"
  },
  {
    "path": "R/testme.R",
    "content": "## This runs 'testme' test inst/testme/test-<name>.R scripts\n## Don't edit - it was autogenerated by inst/testme/deploy.R\ntestme <- function(name) {\n  path <- system.file(package = 'future.apply', 'testme', mustWork = TRUE)\n  Sys.setenv(R_TESTME_PATH = path)\n  Sys.setenv(R_TESTME_PACKAGE = 'future.apply')\n  Sys.setenv(R_TESTME_NAME = name)\n  on.exit(Sys.unsetenv('R_TESTME_NAME'))\n  source(file.path(path, 'run.R'))\n}\n"
  },
  {
    "path": "R/utils,conditions.R",
    "content": "stopf <- function(fmt, ..., call. = TRUE, domain = NULL) {  #nolint\n  msg <- sprintf(fmt, ...)\n  msg <- .makeMessage(msg, domain = domain)\n  if (is.call(call.)) {\n    call <- call.\n  } else if (isTRUE(call.)) {\n    call <- sys.call(which = -1L)\n  } else {\n    call <- NULL\n  }\n  cond <- simpleError(msg, call = call)\n  stop(cond)\n}\n\nwarnf <- function(fmt, ..., call. = TRUE, immediate. = FALSE, domain = NULL) {  #nolint\n  msg <- sprintf(fmt, ...)\n  ## Cannot tweak 'call' when immediate. = TRUE\n  if (isTRUE(immediate.)) {\n    warning(msg, call. = call., immediate. = immediate., domain = domain)\n  } else {\n    msg <- .makeMessage(msg, domain = domain)\n    if (is.call(call.)) {\n      call <- call.\n    } else if (isTRUE(call.)) {\n      call <- sys.call(which = -1L)\n    } else {\n      call <- NULL\n    }\n    cond <- simpleWarning(msg, call = call)\n    warning(cond)\n  }\n}\n\nmsgf <- function(fmt, ..., appendLF = FALSE, domain = NULL) {  #nolint\n  message(sprintf(fmt, ...), appendLF = appendLF, domain = domain)\n}\n"
  },
  {
    "path": "R/utils-debug.R",
    "content": "now <- function(x = Sys.time(), format = \"[%H:%M:%OS3] \") {\n  ## format(x, format = format) ## slower\n  format(as.POSIXlt(x, tz = \"\"), format = format)\n}\n\ndebug_indent <- local({\n  symbols <- rep(c(\"|\", \":\", \".\", \"'\", \",\", \";\", \"`\"), times = 10L)\n  function() {\n    depth <- length(.debug[[\"stack\"]])\n    if (depth == 0) return(\"\")\n    indent <- getOption(\"future.debug.indent\", \" \")\n    paste(paste(symbols[seq_len(depth)], indent, sep = \"\"), collapse = \"\")\n  }\n})\n\nif (!exists(\".debug\", inherits = FALSE)) .debug <- new.env(parent = emptyenv())\nif (!\"stack\" %in% names(\".debug\")) .debug$stack <- list()\n\nmdebug_push <- function(...) {\n  msg <- mdebug(...)\n  .debug$stack <- c(.debug$stack, msg)\n  invisible(msg)\n}\n\nmdebugf_push <- function(...) {\n  msg <- mdebugf(...)\n  .debug$stack <- c(.debug$stack, msg)\n  invisible(msg)\n}\n\nmdebug_pop <- function(...) {\n  n <- length(.debug$stack)\n  msg <- c(...)\n  if (length(msg) == 0) {\n    msg <- .debug$stack[n]\n    msg <- sprintf(\"%s done\", msg)\n  }\n  .debug$stack <- .debug$stack[-n]\n  if (length(msg) == 0 || !is.na(msg)) mdebug(msg)\n}\n\nmdebugf_pop <- function(...) {\n  n <- length(.debug$stack)\n  msg <- .debug$stack[n]\n  .debug$stack <- .debug$stack[-n]\n  mdebug(sprintf(\"%s done\", msg))\n}\n\nmdebug <- function(..., prefix = now()) {\n  prefix <- paste(prefix, debug_indent(), sep = \"\")\n  msg <- paste(..., sep = \"\")\n  message(sprintf(\"%s%s\", prefix, msg))\n  invisible(msg)\n}\n\nmdebugf <- function(..., appendLF = TRUE, prefix = now()) {\n  prefix <- paste(prefix, debug_indent(), sep = \"\")\n  msg <- sprintf(...)\n  message(sprintf(\"%s%s\", prefix, msg), appendLF = appendLF)\n  invisible(msg)\n}\n\n#' @importFrom utils capture.output\nmprint <- function(..., appendLF = TRUE, prefix = now()) {\n  prefix <- paste(prefix, debug_indent(), sep = \"\")\n  message(paste(prefix, capture.output(print(...)), sep = \"\", collapse = \"\\n\"), appendLF = appendLF)\n}\n\n#' @importFrom utils capture.output str\nmstr <- function(..., appendLF = TRUE, prefix = now()) {\n  prefix <- paste(prefix, debug_indent(), sep = \"\")\n  message(paste(prefix, capture.output(str(...)), sep = \"\", collapse = \"\\n\"), appendLF = appendLF)\n}\n"
  },
  {
    "path": "R/utils.R",
    "content": "isFALSE <- function(x) {\n  is.logical(x) && length(x) == 1L && !is.na(x) && !x\n}\n\nisNA <- function(x) {\n  is.logical(x) && length(x) == 1L && is.na(x)\n}\n\nstop_if_not <- function(...) {\n  res <- list(...)\n  for (ii in 1L:length(res)) {\n    res_ii <- .subset2(res, ii)\n    if (length(res_ii) != 1L || is.na(res_ii) || !res_ii) {\n        mc <- match.call()\n        call <- deparse(mc[[ii + 1]], width.cutoff = 60L)\n        if (length(call) > 1L) call <- paste(call[1L], \"....\")\n        stopf(\"%s is not TRUE\", sQuote(call), call. = FALSE, domain = NA)\n    }\n  }\n  \n  NULL\n}\n\n## From R.utils 2.0.2 (2015-05-23)\nhpaste <- function(..., sep = \"\", collapse = \", \", lastCollapse = NULL, maxHead = if (missing(lastCollapse)) 3 else Inf, maxTail = if (is.finite(maxHead)) 1 else Inf, abbreviate = \"...\") {\n  if (is.null(lastCollapse)) lastCollapse <- collapse\n\n  # Build vector 'x'\n  x <- paste(..., sep = sep)\n  n <- length(x)\n\n  # Nothing todo?\n  if (n == 0) return(x)\n  if (is.null(collapse)) return(x)\n\n  # Abbreviate?\n  if (n > maxHead + maxTail + 1) {\n    head <- x[seq_len(maxHead)]\n    tail <- rev(rev(x)[seq_len(maxTail)])\n    x <- c(head, abbreviate, tail)\n    n <- length(x)\n  }\n\n  if (!is.null(collapse) && n > 1) {\n    if (lastCollapse == collapse) {\n      x <- paste(x, collapse = collapse)\n    } else {\n      xT <- paste(x[1:(n-1)], collapse = collapse)\n      x <- paste(xT, x[n], sep = lastCollapse)\n    }\n  }\n\n  x\n} # hpaste()\n\ntrim <- function(s) sub(\"[\\t\\n\\f\\r ]+$\", \"\", sub(\"^[\\t\\n\\f\\r ]+\", \"\", s))\n\ncomma <- function(x, sep = \", \") paste(x, collapse = sep)\n\ncommaq <- function(x, sep = \", \") paste(sQuote(x), collapse = sep)\n\nif (getRversion() < \"4.0.0\") {\n  ## When 'default' is specified, this is 30x faster than\n  ## base::getOption().  The difference is that here we use\n  ## use names(.Options) whereas in 'base' names(options())\n  ## is used.\n  getOption <- local({\n    go <- base::getOption\n    function(x, default = NULL) {\n      if (missing(default) || match(x, table = names(.Options), nomatch = 0L) > 0L) go(x) else default\n    }\n  })\n}\n\n#' @importFrom future FutureError\n#' @importFrom utils capture.output head str\nassert_values2 <- function(nX, values, values2, fcn_name, debug = FALSE) {\n  if (length(values2) != nX) {\n    chunk_sizes <- sapply(values, FUN = length)\n    chunk_sizes <- table(chunk_sizes)\n    chunk_summary <- sprintf(\"%d chunks with %s elements\",\n                             chunk_sizes, names(chunk_sizes))\n    chunk_summary <- paste(chunk_summary, collapse = \", \")\n    msg <- sprintf(\"Unexpected error in %s(): After gathering and merging the values from %d chunks in to a list, the total number of elements (= %d) does not match the number of input elements in 'X' (= %d). There were in total %d chunks and %d elements (%s)\", fcn_name, length(values), length(values2), nX, length(values), sum(chunk_sizes), chunk_summary)\n    if (debug) {\n      mdebug(msg)\n      mprint(chunk_sizes)\n      mdebug(\"Results before merge chunks:\")\n      mstr(values)\n      mdebug(\"Results after merge chunks:\")\n      mstr(values2)\n    }\n    msg <- sprintf(\"%s. Example of the first few values: %s\", msg,\n                   paste(capture.output(str(head(values2, 3L))),\n                         collapse = \"\\\\n\"))\n    ex <- FutureError(msg)\n    stop(ex)\n  }\n}\n\n\nstealth_sample.int <- function(n, size = n, replace = FALSE, ...) {\n  oseed <- .GlobalEnv$.Random.seed\n  on.exit({\n    if (is.null(oseed)) {\n      rm(list = \".Random.seed\", envir = .GlobalEnv, inherits = FALSE)\n    } else {\n      .GlobalEnv$.Random.seed <- oseed\n    }\n  })\n  sample.int(n = n, size = size, replace = replace, ...)\n}\n\n\n#' @importFrom utils packageVersion\nfuture_version <- local({\n  ver <- NULL\n  function() {\n    if (is.null(ver)) ver <<- packageVersion(\"future\")\n    ver\n  }\n})\n"
  },
  {
    "path": "R/zzz.R",
    "content": ".package <- new.env()\n\n## covr: skip=all\n.onLoad <- function(libname, pkgname) {\n  .package[[\"version\"]] <- utils::packageVersion(pkgname)\n\n  import_future_functions()\n\n  update_package_option(\"future.apply.debug\", mode = \"logical\")\n  debug <- getOption(\"future.apply.debug\", FALSE)\n\n  if (debug) {\n    envs <- Sys.getenv()\n    envs <- envs[grep(\"R_FUTURE_APPLY_\", names(envs), fixed = TRUE)]\n    envs <- sprintf(\"- %s=%s\", names(envs), sQuote(envs))\n    mdebug(paste(c(\"R environment variables specific to future.apply:\", envs), collapse = \"\\n\"))\n  }\n\n  ## Set future options based on environment variables\n  update_package_options(debug = debug)\n}\n"
  },
  {
    "path": "README.md",
    "content": "\n\n<div id=\"badges\"><!-- pkgdown markup -->\n<a href=\"https://CRAN.R-project.org/web/checks/check_results_future.apply.html\"><img border=\"0\" src=\"https://www.r-pkg.org/badges/version/future.apply\" alt=\"CRAN check status\"/></a> <a href=\"https://github.com/futureverse/future.apply/actions?query=workflow%3AR-CMD-check\"><img border=\"0\" src=\"https://github.com/futureverse/future.apply/actions/workflows/R-CMD-check.yaml/badge.svg?branch=develop\" alt=\"R CMD check status\"/></a>     <a href=\"https://app.codecov.io/gh/futureverse/future.apply\"><img border=\"0\" src=\"https://codecov.io/gh/futureverse/future.apply/branch/develop/graph/badge.svg\" alt=\"Coverage Status\"/></a> \n</div>\n\n# future.apply: Apply Function to Elements in Parallel using Futures \n\n## Introduction\n\nThe purpose of this package is to provide worry-free parallel alternatives to base-R \"apply\" functions, e.g. `apply()`, `lapply()`, and `vapply()`.  The goal is that one should be able to replace any of these in the core with its futurized equivalent and things will just work.  For example, instead of doing:\n```r\nlibrary(datasets)\nlibrary(stats)\ny <- lapply(mtcars, FUN = mean, trim = 0.10)\n```\none can do:\n```r\nlibrary(future.apply)\nplan(multisession) ## Run in parallel on local computer\n\nlibrary(datasets)\nlibrary(stats)\ny <- future_lapply(mtcars, FUN = mean, trim = 0.10)\n```\n\nReproducibility is part of the core design, which means that perfect, parallel random number generation (RNG) is supported regardless of the amount of chunking, type of load balancing, and future backend being used.  To enable parallel RNG, use argument `future.seed = TRUE`.\n\n\n## Role\n\nWhere does the **[future.apply]** package fit in the software stack?  You can think of it as a sibling to **[foreach]**, **[furrr]**, **[BiocParallel]**, **[plyr]**, etc.  Just as **parallel** provides `parLapply()`, **foreach** provides `foreach()`, **BiocParallel** provides `bplapply()`, and **plyr** provides `llply()`, **future.apply** provides `future_lapply()`.  Below is a table summarizing this idea:\n\n<table>\n<tr>\n<th>Package</th>\n<th>Functions</th>\n<th>Backends</th>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=future.apply\"><strong>future.apply</strong></a><br>\n<br>\n</td>\n<td>\nFuture-versions of common goto <code>*apply()</code> functions available in base R (of the <strong>base</strong> and <strong>stats</strong> packages):<br>\n<code>future_apply()</code>, \n<code>future_by()</code>, \n<code>future_eapply()</code>, \n<code>future_Filter()</code>, \n<code>future_lapply()</code>, \n<code>future_kernapply()</code>,\n<code>future_Map()</code>, \n<code>future_mapply()</code>, \n<code>future_.mapply()</code>, \n<code>future_replicate()</code>,\n<code>future_sapply()</code>,\n<code>future_tapply()</code>, and\n<code>future_vapply()</code>.\n<br>\n<em>The following function is not implemented:</em><br>\n<code>future_rapply()</code><br>\n</td>\n<td>\nAll <strong>future</strong> backends\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<strong>parallel</strong>\n</td>\n<td>\n<code>mclapply()</code>, <code>mcmapply()</code>,\n<code>clusterMap()</code>, <code>parApply()</code>, <code>parLapply()</code>, <code>parSapply()</code>, ...\n</td>\n<td>\nBuilt-in and conditional on operating system</a>\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=foreach\"><strong>foreach</strong></a>\n</td>\n<td>\n<code>foreach()</code>,\n<code>times()</code>\n</td>\n<td>\nAll <strong>future</strong> backends via <a href=\"https://cran.r-project.org/package=doFuture\"><strong>doFuture</strong></a>\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=furrr\"><strong>furrr</strong></a>\n</td>\n<td>\n<code>future_imap()</code>,\n<code>future_map()</code>,\n<code>future_pmap()</code>,\n<code>future_map2()</code>,\n...\n</td>\n<td>\nAll <strong>future</strong> backends\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://bioconductor.org/packages/release/bioc/html/BiocParallel.html\"><strong>BiocParallel</strong></a>\n</td>\n<td>\nBioconductor's parallel mappers:<br>\n<code>bpaggregate()</code>,\n<code>bpiterate()</code>,\n<code>bplapply()</code>, and\n<code>bpvec()</code>\n</td>\n<td>\nAll <strong>future</strong> backends via <a href=\"https://cran.r-project.org/package=doFuture\"><strong>doFuture</strong></a> (because it supports <strong>foreach</strong>) or via <a href=\"https://github.com/futureverse/BiocParallel.FutureParam\"><strong>BiocParallel.FutureParam</strong></a> (direct BiocParallelParam support; prototype)\n</td>\n</tr>\n\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=plyr\"><strong>plyr</strong></a>\n</td>\n<td>\n<code>**ply(..., .parallel = TRUE)</code> functions:<br>\n<code>aaply()</code>,\n<code>ddply()</code>,\n<code>dlply()</code>,\n<code>llply()</code>, ...\n</td>\n<td>\nAll <strong>future</strong> backends via <a href=\"https://cran.r-project.org/package=doFuture\"><strong>doFuture</strong></a> (because it uses <strong>foreach</strong> internally)\n</td>\n</tr>\n\n</table>\n\nNote that, except for the built-in **parallel** package, none of these higher-level APIs implement their own parallel backends, but they rather enhance existing ones.  The **foreach** framework leverages backends such as **[doParallel]**, **[doMC]** and **[doFuture]**, and the **future.apply** framework leverages the **[future]** ecosystem and therefore backends such as built-in **parallel**, **[future.callr]**, and **[future.batchtools]**.\n\nBy separating `future_lapply()` and friends from the **[future]** package, it helps clarifying the purpose of the **future** package, which is to define and provide the core Future API, which higher-level parallel APIs can build on and for which any futurized parallel backends can be plugged into.\n\nThe API and identity of the **future.apply** package will be kept close to the `*apply()` functions in base R.  In other words, it will _neither_ keep growing nor be expanded with new, more powerful apply-like functions beyond those core ones in base R.  Such extended functionality should be part of a separate package.\n\n\n[batchtools]: https://cran.r-project.org/package=batchtools\n[BiocParallel]: https://bioconductor.org/packages/BiocParallel/\n[doFuture]: https://cran.r-project.org/package=doFuture\n[doMC]: https://cran.r-project.org/package=doMC\n[doParallel]: https://cran.r-project.org/package=doParallel\n[foreach]: https://cran.r-project.org/package=foreach\n[future]: https://cran.r-project.org/package=future\n[future.apply]: https://cran.r-project.org/package=future.apply\n[future.batchtools]: https://cran.r-project.org/package=future.batchtools\n[future.callr]: https://cran.r-project.org/package=future.callr\n[furrr]: https://cran.r-project.org/package=furrr\n[plyr]: https://cran.r-project.org/package=plyr\n\n## Installation\nR package future.apply is available on [CRAN](https://cran.r-project.org/package=future.apply) and can be installed in R as:\n```r\ninstall.packages(\"future.apply\")\n```\n\n\n### Pre-release version\n\nTo install the pre-release version that is available in Git branch `develop` on GitHub, use:\n```r\nremotes::install_github(\"futureverse/future.apply\", ref=\"develop\")\n```\nThis will install the package from source.  \n\n<!-- pkgdown-drop-below -->\n\n\n## Contributing\n\nTo contribute to this package, please see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n"
  },
  {
    "path": "cran-comments.md",
    "content": "# CRAN submission future.apply 1.11.3\n\non 2024-10-27\n\nI've verified this submission has no negative impact on any of the 168 reverse package dependencies available on CRAN (n=161) and Bioconductor (n=7).\n\n\n## Notes not sent to CRAN\n\n### R CMD check validation\n\nThe package has been verified using `R CMD check --as-cran` on:\n\n| R version     | GitHub | mac/win-builder |\n| ------------- | ------ | --------------- |\n| 3.6.x         | L      |                 |\n| 4.1.x         | L      |                 |\n| 4.2.x         | L      |                 |\n| 4.3.x         | L M W  |    W            |\n| 4.4.x         | L M W  | M1 W            |\n| devel         | L M W  |    W            |\n\n*Legend: OS: L = Linux, M = macOS, M1 = macOS M1, W = Windows*\n\nIt has also be verified using various R-hub v2 checks.\n"
  },
  {
    "path": "incl/OVERVIEW.md",
    "content": "<%\n## Reuse the main vignette\nmd <- R.rsp::rstring(file=\"vignettes/future.apply-1-overview.md.rsp\", postprocess=FALSE)\n\n## Drop the header, i.e. anything before the first \"H2\" header\nmd <- unlist(strsplit(md, split=\"\\n\", fixed=TRUE))\nrow <- grep(\"^## \", md)[1]\nif (!is.na(row)) md <- md[-seq_len(row-1)]\n\n## Drop the footer, i.e. anything after the first horizontal line\nrow <- grep(\"^---\", md)[1]\nif (!is.na(row)) md <- md[seq_len(row-1)]\n\n## Turn otherwise local links to CRAN for README.md\nmd <- gsub(\": (future-.*[.]html)\",\n           \": https://cran.r-project.org/web/packages/future.apply/vignettes/\\\\1\", md)\n\n## Output\ncat(md, sep=\"\\n\")\n%>\n"
  },
  {
    "path": "incl/future_Filter.R",
    "content": "## ---------------------------------------------------------\n## Filter()\n## ---------------------------------------------------------\nis_even <- function(x) { x %% 2 == 0 }\nx <- sample.int(100, size = 1000, replace = TRUE)\ny <- future_Filter(is_even, x)\n\n\n"
  },
  {
    "path": "incl/future_apply.R",
    "content": "## ---------------------------------------------------------\n## apply()\n## ---------------------------------------------------------\nX <- matrix(c(1:4, 1, 6:8), nrow = 2L)\n\nY0 <- apply(X, MARGIN = 1L, FUN = table)\nY1 <- future_apply(X, MARGIN = 1L, FUN = table)\nprint(Y1)\nstopifnot(all.equal(Y1, Y0, check.attributes = FALSE)) ## FIXME\n\nY0 <- apply(X, MARGIN = 1L, FUN = stats::quantile)\nY1 <- future_apply(X, MARGIN = 1L, FUN = stats::quantile)\nprint(Y1)\nstopifnot(all.equal(Y1, Y0))\n\n\n## ---------------------------------------------------------\n## Parallel Random Number Generation\n## ---------------------------------------------------------\n\\donttest{\n## Regardless of the future plan, the number of workers, and\n## where they are, the random numbers produced are identical\n\nX <- matrix(c(1:4, 1, 6:8), nrow = 2L)\n\nplan(multisession)\nset.seed(0xBEEF)\nY1 <- future_apply(X, MARGIN = 1L, FUN = sample, future.seed = TRUE)\nprint(Y1)\n\nplan(sequential)\nset.seed(0xBEEF)\nY2 <- future_apply(X, MARGIN = 1L, FUN = sample, future.seed = TRUE)\nprint(Y2)\n\nstopifnot(all.equal(Y1, Y2))\n}\n\n\\dontshow{\n## R CMD check: make sure any open connections are closed afterward\nif (!inherits(plan(), \"sequential\")) plan(sequential)\n}\n"
  },
  {
    "path": "incl/future_by.R",
    "content": "## ---------------------------------------------------------\n## by()\n## ---------------------------------------------------------\nlibrary(datasets) ## warpbreaks\nlibrary(stats)    ## lm()\n\ny0 <- by(warpbreaks, warpbreaks[,\"tension\"],\n         function(x) lm(breaks ~ wool, data = x))\n\nplan(multisession)\ny1 <- future_by(warpbreaks, warpbreaks[,\"tension\"],\n                function(x) lm(breaks ~ wool, data = x))\n\nplan(sequential)\ny2 <- future_by(warpbreaks, warpbreaks[,\"tension\"],\n                function(x) lm(breaks ~ wool, data = x))\n"
  },
  {
    "path": "incl/future_lapply.R",
    "content": "## ---------------------------------------------------------\n## lapply(), sapply(), tapply()\n## ---------------------------------------------------------\nx <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE, FALSE, FALSE, TRUE))\ny0 <- lapply(x, FUN = quantile, probs = 1:3/4)\ny1 <- future_lapply(x, FUN = quantile, probs = 1:3/4)\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\ny0 <- sapply(x, FUN = quantile)\ny1 <- future_sapply(x, FUN = quantile)\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\ny0 <- vapply(x, FUN = quantile, FUN.VALUE = double(5L))\ny1 <- future_vapply(x, FUN = quantile, FUN.VALUE = double(5L))\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\n\n## ---------------------------------------------------------\n## Parallel Random Number Generation\n## ---------------------------------------------------------\n\\donttest{\n## Regardless of the future plan, the number of workers, and\n## where they are, the random numbers produced are identical\n\nplan(multisession)\nset.seed(0xBEEF)\ny1 <- future_lapply(1:5, FUN = rnorm, future.seed = TRUE)\nstr(y1)\n\nplan(sequential)\nset.seed(0xBEEF)\ny2 <- future_lapply(1:5, FUN = rnorm, future.seed = TRUE)\nstr(y2)\n\nstopifnot(all.equal(y1, y2))\n}\n\n\n## ---------------------------------------------------------\n## Process chunks of data.frame rows in parallel\n## ---------------------------------------------------------\niris <- datasets::iris\nchunks <- split(iris, seq(1, nrow(iris), length.out = 3L))\ny0 <- lapply(chunks, FUN = function(iris) sum(iris$Sepal.Length))\ny0 <- do.call(sum, y0)\ny1 <- future_lapply(chunks, FUN = function(iris) sum(iris$Sepal.Length))\ny1 <- do.call(sum, y1)\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\n\n## ---------------------------------------------------------\n## Remember to pass down '...' arguments\n## ---------------------------------------------------------\n## It is important that we don't use '...' as a global variable,\n## as attempted in the following not_okay_fcn()\nbad_fcn <- function(X, ...) {\n  y <- future_lapply(X, FUN = function(x) {\n    mean(x, ...)  ## here '...' is a global variable\n  })\n  y\n}\n\n## Instead, make sure to pass '...' via arguments all the way through\ngood_fcn <- function(X, ...) { ## outer '...'\n  y <- future_lapply(X, FUN = function(x, ...) {\n    mean(x, ...)  ## here '...' is an argument of FUN()\n  }, ...) ## pass outer '...' to FUN()\n  y\n}\n\n\n\\dontshow{\n## R CMD check: make sure any open connections are closed afterward\nif (!inherits(plan(), \"sequential\")) plan(sequential)\n}\n"
  },
  {
    "path": "incl/future_mapply.R",
    "content": "## ---------------------------------------------------------\n## mapply()\n## ---------------------------------------------------------\ny0 <- mapply(rep, 1:4, 4:1)\ny1 <- future_mapply(rep, 1:4, 4:1)\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(rep, times = 1:4, x = 4:1)\ny1 <- future_mapply(rep, times = 1:4, x = 4:1)\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(rep, times = 1:4, MoreArgs = list(x = 42))\ny1 <- future_mapply(rep, times = 1:4, MoreArgs = list(x = 42))\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(function(x, y) seq_len(x) + y,\n             c(a =  1, b = 2, c = 3),  # names from first\n             c(A = 10, B = 0, C = -10))\ny1 <- future_mapply(function(x, y) seq_len(x) + y,\n                    c(a =  1, b = 2, c = 3),  # names from first\n                    c(A = 10, B = 0, C = -10))\nstopifnot(identical(y1, y0))\n\nword <- function(C, k) paste(rep.int(C, k), collapse = \"\")\ny0 <- mapply(word, LETTERS[1:6], 6:1, SIMPLIFY = FALSE)\ny1 <- future_mapply(word, LETTERS[1:6], 6:1, SIMPLIFY = FALSE)\nstopifnot(identical(y1, y0))\n\n\n## ---------------------------------------------------------\n## Parallel Random Number Generation\n## ---------------------------------------------------------\n\\donttest{\n## Regardless of the future plan, the number of workers, and\n## where they are, the random numbers produced are identical\n\nplan(multisession)\nset.seed(0xBEEF)\ny1 <- future_mapply(stats::runif, n = 1:4, max = 2:5,\n                    MoreArgs = list(min = 1), future.seed = TRUE)\nprint(y1)\n\nplan(sequential)\nset.seed(0xBEEF)\ny2 <- future_mapply(stats::runif, n = 1:4, max = 2:5,\n                    MoreArgs = list(min = 1), future.seed = TRUE)\nprint(y2)\n\nstopifnot(all.equal(y1, y2))\n}\n\n\\dontshow{\n## R CMD check: make sure any open connections are closed afterward\nif (!inherits(plan(), \"sequential\")) plan(sequential)\n}\n"
  },
  {
    "path": "incl/make_rng_seeds.R",
    "content": "## Set up L'Ecuyer-CMRG random seeds for 100 parallel tasks\n## based on .Random.seed in the current R process\nseeds <- make_rng_seeds(100L, seed = TRUE)\nstr(seeds)\n"
  },
  {
    "path": "incl/random_seed_utils.R",
    "content": "## This example gives identical results in the two\n## approaches only if .Random.seed already exists\nseed_org <- next_random_seed()\nset.seed(42)\n\n## Draw two random number from 1:100 one after the other\nseed_before <- get_random_seed()\nx <- sample.int(100L, size = 1L)\ny <- sample.int(100L, size = 1L)\nseed_after <- get_random_seed()\nprint(c(x, y))\n\n## Draw two random number from 1:100 at once\nset_random_seed(seed_before)\nz <- sample.int(100L, size = 2L)\nseed_after2 <- get_random_seed()\nprint(z)\n\n## The RNG state is the same after the second ...\n## run as after the first, two-step, approach\nstopifnot(identical(seed_after2, seed_after))\n\n## .... and the exact same set of random numbers where\n## drawn [only true in R (>= 4.0.0)]\nif (getRversion() >= \"4.0.0\") {\n  stopifnot(identical(z, c(x, y)))\n} else {\n  stopifnot(identical(z[seq_along(x)], x))\n}\n\nset_random_seed(seed_org)\nstopifnot(identical(get_random_seed(), seed_org))\n"
  },
  {
    "path": "inst/CITATION",
    "content": "utils::bibentry(\n  header = \"Please cite 'future' and the future framework using the following references:\",\n\n  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  # BibTeX entry:\n  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  bibtype = \"article\",\n  key = \"RJ-2021-048\",\n  author = \"Henrik Bengtsson\",\n  title = \"A Unifying Framework for Parallel and Distributed Processing in R using Futures\",\n  year = \"2021\",\n  journal = \"The R Journal\",\n  doi = \"10.32614/RJ-2021-048\",\n  url = \"https://doi.org/10.32614/RJ-2021-048\",\n  pages = \"208--227\",\n  volume = \"13\",\n  number = \"2\",\n\n  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  # Plain-text citation:\n  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n  textVersion = paste0(\n    \"Henrik Bengtsson, \",\n    \"A Unifying Framework for Parallel and Distributed Processing in R using Futures, \",\n    \"The R Journal (2021) 13:2, pages 208-227, \",\n    \"doi:10.32614/RJ-2021-048\"\n  )\n)\n"
  },
  {
    "path": "inst/WORDLIST",
    "content": "AppVeyor\narity\nbatchtools\nbenchmarking\nBiocParallel\ncallr\nCMD\nCMRG\ndoFuture\ndoMC\ndoParallel\neapply\nforeach\nfurrr\nfuturized\nglobals\nHPC\nL'Ecuyer\nlapply\nmacOS\nmapply\nmd\nplyr\npre\nPre\npregenerating\nreproducibility\nReproducibility\nRoadmap\nsapply\nSGE\nSlurm\nstringsAsFactors\ntapply\nvapply\nvectorize\n"
  },
  {
    "path": "inst/testme/_epilogue/001.undo-future.R",
    "content": "## Undo future debug\noptions(future.debug = FALSE)\n\n## Undo future strategy\nfuture::plan(oplan)\n"
  },
  {
    "path": "inst/testme/_epilogue/002.undo-state.R",
    "content": "testme <- as.environment(\"testme\")\nhpaste <- future:::hpaste\n\n## Undo options\n## (a) Reset\noptions(oopts0)\n\n## (b) Remove added\nlocal({\n  added <- setdiff(names(options()), names(oopts0))\n  opts <- vector(\"list\", length = length(added))\n  names(opts) <- added\n  options(opts)\n})\n\n## (c) Assert that everything was undone\nif (!identical(options(), oopts0)) {\n  message(\"Failed to undo options:\")\n  oopts <- options()\n  message(sprintf(\" - Expected options: [n=%d] %s\",\n                  length(oopts0), hpaste(sQuote(names(oopts0)))))\n  extra <- setdiff(names(oopts), names(oopts0))\n  message(paste(sprintf(\" - Options still there: [n=%d]\", length(extra)),\n                hpaste(sQuote(extra))))\n  missing <- setdiff(names(oopts0), names(oopts))\n  message(paste(sprintf(\" - Options missing: [n=%d]\", length(missing)),\n                hpaste(sQuote(missing))))\n                \n  message(\"Differences option by option:\")\n  void <- lapply(names(oopts0), FUN = function(name) {\n    value0 <- oopts0[[name]]\n    value  <- oopts[[name]]\n    if (!identical(value, value0)) {\n      if (testme[[\"debug\"]]) {\n        utils::str(list(name = name, expected = value0, actual = value))\n      }\n    }\n  })\n}\n\n\n## Undo system environment variables\n## (a) Reset\ndo.call(Sys.setenv, args=as.list(oenvs0))\n## (b) Removed added\nadded <- setdiff(names(Sys.getenv()), names(oenvs0))\nSys.unsetenv(added)\n## (c) Assert that everything was undone\nif (!identical(Sys.getenv(), oenvs0)) {\n  message(\"Failed to undo environment variables:\")\n  oenvs <- Sys.getenv()\n  message(sprintf(\" - Expected environment variables: [n=%d] %s\",\n                  length(oenvs0), hpaste(sQuote(names(oenvs0)))))\n  extra <- setdiff(names(oenvs), names(oenvs0))\n  message(paste(sprintf(\" - Environment variables still there: [n=%d]\", length(extra)),\n                hpaste(sQuote(extra))))\n  missing <- setdiff(names(oenvs0), names(oenvs))\n  message(paste(sprintf(\" - Environment variables missing: [n=%d]\", length(missing)),\n                hpaste(sQuote(missing))))\n  message(\"Differences environment variable by environment variable:\")\n  void <- lapply(names(oenvs0), FUN = function(name) {\n    value0 <- unname(oenvs0[name])\n    value  <- unname(oenvs[name])\n    if (!identical(value, value0)) {\n      if (testme[[\"debug\"]]) {\n        utils::str(list(name = name, expected = value0, actual = value))\n      }\n    }\n  })\n}\n\n\n## Assert undo was successful\nif (testme[[\"debug\"]]) {\n  stopifnot(identical(options(), oopts0))\n}\n\n## Undo variables\nrm(list = c(setdiff(ls(envir = globalenv()), ovars)), envir = globalenv())\n"
  },
  {
    "path": "inst/testme/_epilogue/090.gc.R",
    "content": "## Travis CI specific: Explicit garbage collection because it\n## looks like Travis CI might run out of memory during 'covr'\n## testing and we now have so many tests. /HB 2017-01-11\nif (\"covr\" %in% loadedNamespaces()) {\n  res <- gc()\n  testme <- as.environment(\"testme\")\n  if (testme[[\"debug\"]]) print(res)\n}\n"
  },
  {
    "path": "inst/testme/_epilogue/099.session_info.R",
    "content": "testme <- as.environment(\"testme\")\nif (testme[[\"debug\"]]) {\n  info <- utils::sessionInfo()\n  message(\"Session information:\")\n  print(info)\n}\n"
  },
  {
    "path": "inst/testme/_epilogue/995.detritus-connections.R",
    "content": "## Look for detritus files\ntestme <- as.environment(\"testme\")\nlocal({\n  delta <- diff_connections(get_connections(), testme[[\"testme_connections\"]])\n  if (any(lengths(delta) > 0)) {\n    message(sprintf(\"Detritus connections generated by test %s:\", sQuote(testme[[\"name\"]])))\n    print(delta)\n  }\n})\n\n\n"
  },
  {
    "path": "inst/testme/_epilogue/999.detritus-files.R",
    "content": "## Look for detritus files\ntestme <- as.environment(\"testme\")\n\nlocal({\n  path <- dirname(tempdir())\n  \n  if (basename(path) == \"working_dir\") {\n    files <- dir(pattern = \"^Rscript\", path = path, all.files = TRUE, full.names = TRUE)\n    if (length(files) > 0L) {\n      message(sprintf(\"Detritus 'Rscript*' files generated by test %s:\", sQuote(testme[[\"name\"]])))\n      print(files)\n      \n      ## Remove detritus files produced by this test script, so that\n      ## other test scripts will not fail because of these files.\n      unlink(files)\n  \n      ## Signal the problem\n      msg <- sprintf(\"Detected 'Rscript*' files: [n=%d] %s\", length(files), paste(sQuote(basename(files)), collapse = \", \"))\n      ## Are detritus files files expected by design on MS Windows?\n      ## If so, produce a warning, otherwise an error\n      if (\"detritus-files\" %in% testme[[\"tags\"]] &&\n          .Platform[[\"OS.type\"]] == \"windows\") {\n        warning(msg, immediate. = TRUE)\n      } else {\n        stop(msg)\n      }\n    }\n  } else {\n    message(sprintf(\"Skipping, because path appears not to be an 'R CMD check' folder: %s\", sQuote(path)))\n  }\n})\n"
  },
  {
    "path": "inst/testme/_prologue/001.load.R",
    "content": "testme <- as.environment(\"testme\")\nloadNamespace(testme[[\"package\"]])\n\n"
  },
  {
    "path": "inst/testme/_prologue/002.record-state.R",
    "content": "## Record original state\novars <- ls(envir = globalenv())\noenvs <- oenvs0 <- Sys.getenv()\noopts0 <- options()\n"
  },
  {
    "path": "inst/testme/_prologue/030.imports.R",
    "content": "## Private future functions\nfold <- future.apply:::fold\nhpaste <- future.apply:::hpaste\nmdebug <- future.apply:::mdebug\nmdebugf <- future.apply:::mdebugf\nimport_from <- future.apply:::import_from\nget_random_seed <- future.apply:::get_random_seed\nset_random_seed <- future.apply:::set_random_seed\nnext_random_seed <- future.apply:::next_random_seed\nas_lecyer_cmrg_seed <- future.apply:::as_lecyer_cmrg_seed\nis_lecyer_cmrg_seed <- future.apply:::is_lecyer_cmrg_seed\nmake_rng_seeds <- future.apply:::make_rng_seeds\n"
  },
  {
    "path": "inst/testme/_prologue/050.utils.R",
    "content": "## Local functions for test scripts\nprintf <- function(...) cat(sprintf(...))\nmstr <- function(...) message(paste(capture.output(str(...)), collapse = \"\\n\"))\n"
  },
  {
    "path": "inst/testme/_prologue/090.context.R",
    "content": "fullTest <- (Sys.getenv(\"_R_CHECK_FULL_\") != \"\")\n\ncovr_testing <- (\"covr\" %in% loadedNamespaces())\non_macos <- grepl(\"^darwin\", R.version$os)\non_githubactions <- as.logical(Sys.getenv(\"GITHUB_ACTIONS\", \"FALSE\"))\n"
  },
  {
    "path": "inst/testme/_prologue/090.options.R",
    "content": "## Default options\noopts <- options(\n  warn = 1L,\n  showNCalls = 500L,\n  mc.cores = 2L,\n  future.debug = FALSE,\n  ## Reset the following during testing in case\n  ## they are set on the test system\n  future.availableCores.system = NULL,\n  future.availableCores.fallback = NULL\n)\n"
  },
  {
    "path": "inst/testme/_prologue/091.envvars.R",
    "content": "## Comment: The below should be set automatically whenever the future package\n## is loaded and 'R CMD check' runs.  The below is added in case R is changed\n## in the future and we fail to detect 'R CMD check'.\nSys.setenv(R_PARALLELLY_MAKENODEPSOCK_CONNECTTIMEOUT = 2 * 60)\nSys.setenv(R_PARALLELLY_MAKENODEPSOCK_TIMEOUT = 2 * 60)\nSys.setenv(R_PARALLELLY_MAKENODEPSOCK_SESSIONINFO_PKGS = TRUE)\nSys.setenv(R_FUTURE_WAIT_INTERVAL = 0.01) ## 0.01s (instead of default 0.2s)\n\n## Label PSOCK cluster workers (to help troubleshooting)\ntest_script <- grep(\"[.]R$\", commandArgs(), value = TRUE)[1]\nif (is.na(test_script)) test_script <- \"UNKNOWN\"\nworker_label <- sprintf(\"future/tests/%s:%s:%s:%s\", test_script, Sys.info()[[\"nodename\"]], Sys.info()[[\"user\"]], Sys.getpid())\nSys.setenv(R_PARALLELLY_MAKENODEPSOCK_RSCRIPT_LABEL = worker_label)\n\n## Reset the following during testing in case\n## they are set on the test system\noenvs2 <- Sys.unsetenv(c(\n  \"R_PARALLELLY_AVAILABLECORES_SYSTEM\",\n  \"R_PARALLELLY_AVAILABLECORES_FALLBACK\",\n  ## SGE\n  \"NSLOTS\", \"PE_HOSTFILE\",\n  ## Slurm\n  \"SLURM_CPUS_PER_TASK\",\n  ## TORQUE / PBS\n  \"NCPUS\", \"PBS_NUM_PPN\", \"PBS_NODEFILE\", \"PBS_NP\", \"PBS_NUM_NODES\"\n))\n"
  },
  {
    "path": "inst/testme/_prologue/099.future-setup.R",
    "content": "## Use sequential futures by default\noplan <- local({\n  oopts <- options(future.debug = FALSE)\n  on.exit(options(oopts))\n  future::plan(future::sequential)\n})\n\n\nsupportedStrategies <- function(cores = NA_integer_, excl = \"cluster\", ...) {\n  strategies <- future:::supportedStrategies(...)\n  strategies <- setdiff(strategies, excl)\n  \n  if (!is.na(cores)) {\n    if (cores == 1L) {\n      strategies <- setdiff(strategies, c(\"multicore\", \"multisession\"))\n    } else if (cores > 1L) {\n      strategies <- setdiff(strategies, \"sequential\")\n    }\n  }\n  \n  strategies\n}\n\navailCores <- min(2L, future::availableCores())\n"
  },
  {
    "path": "inst/testme/_prologue/995.detrius-connections.R",
    "content": "get_connections <- function() {\n  cons <- lapply(getAllConnections(), FUN = function(idx) {\n    tryCatch({\n      con <- getConnection(idx)\n      as.data.frame(c(index = idx, summary(con)))\n    }, error = function(e) {\n      NULL\n    })\n  })\n  do.call(rbind, cons)\n}\n\ndiff_connections <- function(after, before) {\n  index <- NULL ## To please R CMD check\n  \n  ## Nothing to do?\n  if (length(before) + length(after) == 0L) {\n    return(c(added = NULL, removed = NULL, replaced = NULL))\n  }\n\n  idxs <- setdiff(after[[\"index\"]], before[[\"index\"]])\n  if (length(idxs) > 0) {\n    added <- subset(after, index %in% idxs)\n    after <- subset(after, ! index %in% idxs)\n  } else {\n    added <- NULL\n  }\n  \n  idxs <- setdiff(before[[\"index\"]], after[[\"index\"]])\n  if (length(idxs) > 0) {\n    removed <- subset(before, index %in% idxs)\n    before <- subset(before, ! index %in% idxs)\n  } else {\n    removed <- NULL\n  }\n\n  idxs <- intersect(before[[\"index\"]], after[[\"index\"]])\n  if (length(idxs) > 0) {\n    replaced <- list()\n    for (idx in idxs) {\n      before_idx <- subset(before, index == idx)\n      after_idx <- subset(after, index == idx)\n      if (!identical(before_idx, after_idx)) {\n        for (name in colnames(after_idx)) {\n          value <- after_idx[[name]]\n          if (!identical(before_idx[[name]], value)) {\n            value <- sprintf(\"%s (was %s)\", value, before_idx[[name]])\n            after_idx[[name]] <- value\n          }\n        }\n        replaced <- c(replaced, list(after_idx))\n      }\n    }\n    replaced <- do.call(rbind, replaced)\n  } else {\n    replaced <- NULL\n  }\n\n  list(added = added, removed = removed, replaced = replaced)\n}\n\ntestme <- as.environment(\"testme\")\ntestme[[\"testme_connections\"]] <- get_connections()\n"
  },
  {
    "path": "inst/testme/deploy.R",
    "content": "#!/usr/bin/env Rscript\n\nsource <- \"./inst/testme\"\nif (!utils::file_test(\"-d\", source)) {\n  stop(\"Source 'testme' folder not found: \", sQuote(source))\n}\n\ntarget <- \"./tests\"\nif (!utils::file_test(\"-d\", target)) {\n  stop(\"Target 'tests' folder not found: \", sQuote(target))\n}\n\nr_path <- \"./R\"\nif (!utils::file_test(\"-d\", r_path)) {\n  stop(\"Target 'R' folder not found: \", sQuote(r_path))\n}\n\ndesc <- \"./DESCRIPTION\"\nif (!utils::file_test(\"-f\", desc)) {\n  stop(\"'DESCRIPTION' file not found: \", sQuote(desc))\n}\npkgname <- read.dcf(desc)[, \"Package\"]\nif (is.na(pkgname) || !nzchar(pkgname)) {\n  stop(\"Failed to infer package name from 'DESCRIPTION' file: \", sQuote(pkgname))\n} else if (!requireNamespace(pkgname)) {\n  stop(\"Package fail to load: \", sQuote(pkgname))\n}\n\n\nfiles <- dir(path = source, pattern = \"^test-.*[.]R$\", full.names = TRUE)\nmessage(sprintf(\"Deploying %d test scripts ...\", length(files)))\n\n## Generate R unit test script\ncode <- c(\n  \"## This runs 'testme' test inst/testme/test-<name>.R scripts\",\n  \"## Don't edit - it was autogenerated by inst/testme/deploy.R\",\n  \"testme <- function(name) {\",\n  sprintf(\"  path <- system.file(package = '%s', 'testme', mustWork = TRUE)\", pkgname),\n  \"  Sys.setenv(R_TESTME_PATH = path)\",\n  sprintf(\"  Sys.setenv(R_TESTME_PACKAGE = '%s')\", pkgname),\n  \"  Sys.setenv(R_TESTME_NAME = name)\",\n  \"  on.exit(Sys.unsetenv('R_TESTME_NAME'))\",\n  \"  source(file.path(path, 'run.R'))\",\n  \"}\"\n)\nwriteLines(code, con = file.path(\"./R/testme.R\"))\n\nfor (kk in seq_along(files)) {\n  file <- files[kk]\n\n  source_file <- basename(file)\n  name <- sub(\"^test-\", \"\", sub(\"[.]R$\", \"\", source_file))\n  target_file <- file.path(target, source_file)\n  \n  message(sprintf(\"%02d/%02d test script %s\", kk, length(files), sQuote(target_file)))\n\n  ## Assert that testme script can be parsed\n  res <- tryCatch(parse(file = file), error = identity)\n  if (inherits(res, \"error\")) {\n    stop(\"Syntax error: \", sQuote(file))\n  }\n\n  ## Generate R unit test script\n  code <- c(\n    \"#! /usr/bin/env Rscript\",\n    sprintf(\"## This runs testme test script inst/testme/test-%s.R\", name),\n    \"## Don't edit - it was autogenerated by inst/testme/deploy.R\",\n    sprintf('%s:::testme(\"%s\")', pkgname, name)\n  )\n  writeLines(code, con = target_file)\n  Sys.chmod(target_file, mode = \"0755\")\n}\n\nmessage(sprintf(\"Deploying %d test scripts ... done\", length(files)))\n"
  },
  {
    "path": "inst/testme/run.R",
    "content": "#!/usr/bin/env Rscript\n\n#' Run a 'testme' Test Script\n#'\n#' R usage:\n#' testme(\"<name>\")\n#'\n#' Command-line usage:\n#' tests/test-<name>.R\n#'\n#' Command-line usage without package re-install:\n#' inst/testme/run.R --name=<test_name>\n#' inst/testme/run.R <test-name.R>\n#'\n#' Options:\n#' --package=<pkg>     The name of the package being tested\n#'                     (Environment variable: `R_TESTME_PACKAGE`)\n#'                     (Default: The `Package` field of the DESCRIPTION file)\n#' --name=<name>       The name of the test to run, used to locate the test\n#'                     script `test-<name>.R`\n#'                     (Environment variable: `R_TESTME_NAME`)\n#' --not-cran          Set environment variable `NOT_CRAN=true`\n#' --coverage=summary  Estimate test code coverage with basic summary\n#' --coverage=tally    Estimate test code coverage with full tally summary\n#' --coverage=report   Estimate test code coverage with full HTML report\n#' --debug             Output debug messages\n#'                     (Environment variable: `R_TESTME_DEBUG`)\n#'\n#' Examples:\n#' testme/test-abc.R\n#' testme/test-abc.R --not-cran\n#' tests/test-cpuLoad.R --coverage=report\n#'\n#' inst/testme/run.R inst/testme/test-abc.R\n#' inst/testme/run.R inst/testme/test-abc.R --coverage\n#'\n#' Environment variables:\n#' * R_TESTME_PACKAGE\n#' * R_TESTME_NAME\n#' * R_TESTME_PATH\n#' * R_TESTME_FILTER_NAME\n#' * R_TESTME_FILTER_TAGS\n#' * R_TESTME_COVERAGE\n#' * R_TESTME_DEBUG\nmain <- function() {\n  cmd_args <- commandArgs(trailingOnly = TRUE)\n  \n  pattern <- \"--package=([[:alpha:][:alnum:]]+)\"\n  idx <- grep(pattern, cmd_args)\n  if (length(idx) > 0L) {\n    stopifnot(length(idx) == 1L)\n    testme_package <- gsub(pattern, \"\\\\1\", cmd_args[idx])\n    cmd_args <- cmd_args[-idx]\n  } else {\n    testme_package <- Sys.getenv(\"R_TESTME_PACKAGE\", NA_character_)\n    if (is.na(testme_package)) {\n      desc <- read.dcf(\"DESCRIPTION\")\n      testme_package <- desc[1, \"Package\"]\n    }\n  }\n  \n  pattern <- \"--path=([[:alpha:][:alnum:]]+)\"\n  idx <- grep(pattern, cmd_args)\n  if (length(idx) > 0L) {\n    stopifnot(length(idx) == 1L)\n    path <- gsub(pattern, \"\\\\1\", cmd_args[idx])\n    cmd_args <- cmd_args[-idx]\n  } else {\n    path <- Sys.getenv(\"R_TESTME_PATH\", NA_character_)\n    if (is.na(path)) {\n      path <- file.path(\"inst\", \"testme\")\n    }\n    if (!utils::file_test(\"-d\", path)) {\n      stop(\"There exist no such 'R_TESTME_PATH' folder: \", sQuote(path))\n    }\n  }\n  \n  pattern <- \"--name=([[:alpha:][:alnum:]]+)\"\n  idx <- grep(pattern, cmd_args)\n  if (length(idx) > 0L) {\n    stopifnot(length(idx) == 1L)\n    testme_name <- gsub(pattern, \"\\\\1\", cmd_args[idx])\n    cmd_args <- cmd_args[-idx]\n  } else {\n    testme_name <- NULL\n  }\n\n  pattern <- \"^--not-cran\"\n  idx <- grep(pattern, cmd_args)\n  if (length(idx) > 0L) {\n    cmd_args <- cmd_args[-idx]\n    Sys.setenv(NOT_CRAN = \"TRUE\")\n  }\n\n  pattern <- \"^--debug\"\n  idx <- grep(pattern, cmd_args)\n  if (length(idx) > 0L) {\n    cmd_args <- cmd_args[-idx]\n    Sys.setenv(R_TESTME_DEBUG = \"TRUE\")\n  }\n\n  pattern <- \"^--coverage(|=([[:alpha:][:alnum:]]+))$\"\n  idx <- grep(pattern, cmd_args)\n  if (length(idx) > 0L) {\n    value <- gsub(pattern, \"\\\\2\", cmd_args[idx])\n    if (!nzchar(value)) {\n      coverage <- \"summary\"\n    } else {\n      coverage <- match.arg(value, choices = c(\"none\", \"summary\", \"tally\", \"report\"))\n    }\n    cmd_args <- cmd_args[-idx]\n  } else {\n    value <- Sys.getenv(\"R_TESTME_COVERAGE\", \"none\")\n    coverage <- match.arg(value, choices = c(\"none\", \"summary\", \"tally\", \"report\"))\n  }\n  if (coverage != \"none\") {\n    if (!utils::file_test(\"-f\", \"DESCRIPTION\")) {\n      stop(\"Current folder does not look like a package folder\")\n    }\n  }\n  \n  ## Fallback for 'testme_name'?\n  if (is.null(testme_name)) {\n    if (length(cmd_args) > 0) {\n      stopifnot(length(cmd_args) == 1L)\n      file <- cmd_args[1]\n      if (utils::file_test(\"-f\", file)) {\n        testme_name <- gsub(\"(^test-|[.]R$)\", \"\", basename(file))\n      } else {\n        stop(\"No such file: \", file)\n      }\n    } else {\n      testme_name <- Sys.getenv(\"R_TESTME_NAME\", NA_character_)\n      if (is.na(testme_name)) {\n        stop(\"testme: Environment variable 'R_TESTME_NAME' is not set\")\n      }\n    }\n  } \n  \n  testme_file <- file.path(path, sprintf(\"test-%s.R\", testme_name))\n  if (!utils::file_test(\"-f\", testme_file)) {\n    stop(\"There exist no such 'testme' file: \", sQuote(testme_file))\n  }\n\n  \n  ## -----------------------------------------------------------------\n  ## testme environment\n  ## -----------------------------------------------------------------\n  on_cran <- function() {\n    not_cran <- Sys.getenv(\"NOT_CRAN\", NA_character_)\n    if (is.na(not_cran)) {\n      not_cran <- FALSE\n    } else {\n      not_cran <- isTRUE(as.logical(not_cran))\n    }\n    !interactive() && !not_cran\n  } ## on_cran()\n  \n  \n  ## Get test script tags\n  tags <- local({\n    lines <- readLines(testme_file, warn = FALSE)\n    pattern <- \"^#'[[:blank:]]+@tags[[:blank:]]+\"\n    lines <- grep(pattern, lines, value = TRUE)\n    tags <- sub(pattern, \"\", lines)\n    tags\n  })\n  if (length(tags) > 0) {\n    tags <- sub(\"[[:blank:]]*$\", \"\", tags)\n    tags <- unlist(strsplit(tags, split = \"[[:blank:]]+\"))\n    tags <- sort(unique(tags))\n  } else {\n    tags <- character(0L)\n  }\n\n  debug <- isTRUE(as.logical(Sys.getenv(\"R_TESTME_DEBUG\")))\n\n  coverage <- match.arg(coverage, choices = c(\"none\", \"summary\", \"tally\", \"report\"))\n\n  ## Create 'testme' environment on the search() path\n  testme_config <- list(\n     testme = TRUE,\n    package = testme_package,\n       name = testme_name,\n       tags = tags,\n     status = \"created\",\n      start = proc.time(),\n     script = testme_file,\n       path = path,\n    on_cran = on_cran(),\n       coverage = coverage,\n      debug = debug\n  )\n  if (\"testme\" %in% search()) detach(name = \"testme\")\n  testme <- attach(testme_config, name = \"testme\", warn.conflicts = FALSE)\n  rm(list = c(\"tags\", \"testme_package\", \"testme_name\", \"testme_file\"))\n  \n\n  ## -----------------------------------------------------------------\n  ## Filters\n  ## -----------------------------------------------------------------\n  ## Skip on CRAN? To run these tests, set env var NOT_CRAN=true\n  if (\"skip_on_cran\" %in% tags && on_cran()) {\n    testme[[\"status\"]] <- \"skipped\"\n  }\n\n  code <- Sys.getenv(\"R_TESTME_FILTER_NAME\", NA_character_)\n  if (!is.na(code)) {\n    expr <- tryCatch(parse(text = code), error = identity)\n    if (inherits(expr, \"error\")) {\n      stop(\"Syntax error in R_TESTME_FILTER_NAME: \", sQuote(code))\n    }\n    \n    keep <- tryCatch(eval(expr, envir = testme), error = identity)\n    if (inherits(keep, \"error\")) {\n      stop(\"Evaluation of R_TESTME_FILTER_NAME=%s produced an error: %s\",\n           sQuote(code), conditionMessage(keep))\n    }\n    if (!isTRUE(keep)) testme[[\"status\"]] <- \"skipped\"\n  }\n  \n  code <- Sys.getenv(\"R_TESTME_FILTER_TAGS\", NA_character_)\n  if (!is.na(code)) {\n    expr <- tryCatch(parse(text = code), error = identity)\n    if (inherits(expr, \"error\")) {\n      stop(\"Syntax error in R_TESTME_FILTER_TAGS: \", sQuote(code))\n    }\n    keep <- tryCatch(eval(expr, envir = testme), error = identity)\n    if (inherits(keep, \"error\")) {\n      stop(\"Evaluation of R_TESTME_FILTER_TAGS=%s produced an error: %s\",\n           sQuote(code), conditionMessage(keep))\n    }\n    if (!isTRUE(keep)) testme[[\"status\"]] <- \"skipped\"\n  }\n  \n  testme_run_test(testme)\n} ## main()\n\n\n\n#' @param testme A names list\n#'\ntestme_run_test <- function(testme) {\n  message(sprintf(\"Test %s ...\", sQuote(testme[[\"name\"]])))\n  if (testme[[\"debug\"]]) {\n    message(\"testme:\")\n    message(paste(utils::capture.output(utils::str(as.list(testme))), collapse = \"\\n\"))\n  }\n\n  path <- testme[[\"path\"]]\n\n  ## Process prologue scripts, if they exist\n  if (testme[[\"status\"]] != \"skipped\" &&\n      utils::file_test(\"-d\", file.path(path, \"_prologue\"))) {\n    testme[[\"status\"]] <- \"prologue\"\n    local({\n      ## Find all prologue scripts\n      files <- dir(file.path(path, \"_prologue\"), pattern = \"*[.]R$\", full.names = TRUE)\n      files <- sort(files)\n      testme[[\"prologue_scripts\"]] <- files\n\n      ## Source all prologue scripts inside the 'testme' environment\n      expr <- bquote({\n        files <- prologue_scripts\n        if (.(testme[[\"debug\"]])) message(sprintf(\"Sourcing %d prologue scripts ...\", length(files)))\n        for (kk in seq_along(files)) {\n          file <- files[kk]\n          if (.(testme[[\"debug\"]])) message(sprintf(\"%02d/%02d prologue script %s\", kk, length(files), sQuote(file)))\n          source(file, local = TRUE)\n        }\n        if (.(testme[[\"debug\"]])) message(sprintf(\"Sourcing %d prologue scripts ... done\", length(files)))\n        rm(list = c(\"kk\", \"file\", \"files\"))\n      })\n      eval(expr, envir = testme)\n    })\n  \n  #  ## In case prologue scripts overwrote some elements in 'testme'\n  #  for (name in names(testme_config)) {\n  #    testme[[name]] <- testme_config[[name]]\n  #  }\n  }\n  \n  \n  ## Run test script\n  ## Note, prologue scripts may trigger test to be skipped\n  if (testme[[\"status\"]] != \"skipped\") {\n    if (testme[[\"debug\"]]) message(\"Running test script: \", sQuote(testme[[\"script\"]]))\n    testme[[\"status\"]] <- \"failed\"\n    str(testme[[\"coverage\"]])\n    if (testme[[\"coverage\"]] != \"none\") {\n      pkg_env <- pkgload::load_all()\n      cov <- covr::environment_coverage(pkg_env[[\"env\"]], test_files = testme[[\"script\"]])\n      ## Keep source files with non-zero coverage\n      tally <- covr::tally_coverage(cov)\n      tally <- subset(tally, value > 0)\n      cov <- cov[covr::display_name(cov) %in% unique(tally$filename)]\n      testme[[\"test_coverage\"]] <- cov\n    } else {\n      testme[[\"test_coverage\"]] <- NULL\n      source(testme[[\"script\"]], echo = TRUE)\n    }\n    testme[[\"status\"]] <- \"success\"\n  }\n  \n  \n  ## Process epilogue scripts, if they exist\n  ## Note, epilogue scripts may change status or produce check errors\n  if (testme[[\"status\"]] == \"success\" &&\n      utils::file_test(\"-d\", file.path(path, \"_epilogue\"))) {\n    testme[[\"status\"]] <- \"epilogue\"\n    local({\n      ## Find all epilogue scripts\n      files <- dir(file.path(path, \"_epilogue\"), pattern = \"*[.]R$\", full.names = TRUE)\n      files <- sort(files)\n      testme[[\"epilogue_scripts\"]] <- files\n    \n      ## Source all epilogue scripts inside the 'testme' environment\n      expr <- bquote({\n        files <- epilogue_scripts\n        if (.(testme[[\"debug\"]])) message(sprintf(\"Sourcing %d epilogue scripts ...\", length(files)))\n        for (kk in seq_along(files)) {\n          file <- files[kk]\n          if (.(testme[[\"debug\"]])) message(sprintf(\"%02d/%02d epilogue script %s\", kk, length(files), sQuote(file)))\n          source(file, local = TRUE)\n        }\n        if (.(testme[[\"debug\"]])) message(sprintf(\"Sourcing %d epilogue scripts ... done\", length(files)))\n        rm(list = c(\"kk\", \"file\", \"files\"))\n      })\n      eval(expr, envir = testme)\n    })\n    testme[[\"status\"]] <- \"success\"\n  }\n  \n  testme[[\"stop\"]] <- proc.time()\n  dt <- testme[[\"stop\"]] - testme[[\"start\"]]\n  dt_str <- sprintf(\"%s=%.1gs\", names(dt), dt)\n  message(\"Test time: \", paste(dt_str, collapse = \", \"))\n  \n  if (\"testme\" %in% search()) detach(name = \"testme\")\n\n  cov <- testme[[\"test_coverage\"]]\n  if (!is.null(cov)) {\n    message(\"Source files covered by the test script:\")\n    if (length(cov) > 0) {\n      print(cov)\n      if (\"tally\" %in% testme[[\"coverage\"]]) {\n        tally <- covr::tally_coverage(cov)\n        print(tally)\n      }\n      if (\"report\" %in% testme[[\"coverage\"]]) {\n        html <- covr::report(cov, browse = FALSE)\n        browseURL(html)\n        Sys.sleep(5.0)\n      }\n    } else {\n      message(\"* No source files were covered by this test!\")\n    }\n  }\n\n  message(sprintf(\"Test %s ... %s\", sQuote(testme[[\"name\"]]), testme[[\"status\"]]))\n} ## testme_run_test()\n\n\nmain()\n"
  },
  {
    "path": "inst/testme/test-fold.R",
    "content": "#' @tags fold\n\nloadNamespace(\"future.apply\")\n\nmessage(\"*** fold() ...\")\n\nx1s <- list(\n  a = NULL,\n  b = 1,\n  c = c(a = 1, b = 2),\n  d = 1:10e3\n)\n\nx2s <- lapply(x1s, FUN = as.list)\nnames(x2s) <- toupper(names(x1s))\n\nx3s <- list(\n  E = data.frame(a = 1:3),\n  F = data.frame(a = 1:3, b = letters[1:3], stringsAsFactors=FALSE)\n)\n\nxs <- c(x1s, x2s, x3s)\n\n\nfcns <- list(\"c\" = base::c, \"cbind\" = base::cbind)\nfor (kk in seq_along(xs)) {\n  x_name <- names(xs)[kk]\n  for (fcn_name in names(fcns)) {\n    fcn <- fcns[[fcn_name]]\n    message(sprintf(\" - #%d. %s(x[['%s']]) ...\", kk, fcn_name, x_name))\n    x <- xs[[kk]]\n    str(list(x = x))\n    \n    y0 <- Reduce(x, f = fcn)\n    y1 <- fold(x, f = fcn)\n    y2 <- fold(x, f = fcn, unname = FALSE)\n    str(list(y0 = y0, y1 = y1, y2 = y2))\n    stopifnot(all.equal(unname(y1), unname(y0)))\n    stopifnot(all.equal(unname(y2), unname(y0)))\n    if (!fcn_name %in% \"cbind\") {\n      stopifnot(all.equal(y1, y0))\n      stopifnot(all.equal(y2, y0))\n    }\n    \n    y0 <- Reduce(x, f = fcn, right = TRUE)\n    y1 <- fold(x, f = fcn, left = FALSE)\n    y2 <- fold(x, f = fcn, left = FALSE, unname = FALSE)\n    str(list(y0 = y0, y1 = y1, y2 = y2))\n    stopifnot(all.equal(unname(y1), unname(y0)))\n    stopifnot(all.equal(unname(y2), unname(y0)))\n    if (!fcn_name %in% \"cbind\") {\n      stopifnot(all.equal(y1, y0))\n      stopifnot(all.equal(y2, y0))\n    }\n    \n    message(sprintf(\" - #%d. %s(x[['%s']]) ... DONE\", kk, fcn_name, x_name))\n  }\n}\n\n\nmake_table <- function(n) {\n  data.frame(key = sample(n), value = sample(n), stringsAsFactors=FALSE)\n}\n\nsizes <- rep(10, 20)\n\nset.seed(3180)\ntables <- lapply(sizes, make_table)\n\nkey_merge <- function(x, y) merge(x, y, by = \"key\", all = FALSE)\n\nsuppressWarnings(\nfolded <- fold(tables, key_merge, left = TRUE, unname = FALSE,\n               threshold = 6L)\n)\n\nsuppressWarnings(\nreduced <- Reduce(key_merge, tables[-1], tables[[1]])\n)\n\nstopifnot(all.equal(unname(folded), unname(reduced)))\n\nmessage(\"*** fold() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_Filter.R",
    "content": "#' @tags future_Filter\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_Filter() ...\")\n\nis_even <- function(x) { x %% 2 == 0 }\nx <- sample.int(100, size = 1000, replace = TRUE)\n\ny_truth <- x[vapply(x, FUN.VALUE = NA, FUN = is_even)]\nstr(y_truth)\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n\n  y <- Filter(is_even, x)\n  str(y)\n\n  stopifnot(identical(y, y_truth))\n  \n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n}\n\nplan(sequential)\n\nmessage(\"*** future_Filter() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_apply.R",
    "content": "#' @tags future_apply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_apply() ...\")\n\nz0 <- NULL\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n\n  message(\"- From example(apply) ...\")\n  X <- matrix(c(1:4, 1, 6:8), nrow = 2L)\n  \n  Y0 <- apply(X, MARGIN = 1L, FUN = table)\n  Y1 <- future_apply(X, MARGIN = 1L, FUN = table)\n  print(Y1)\n  stopifnot(all.equal(Y1, Y0, check.attributes = FALSE)) ## FIXME\n\n  Y2 <- future_apply(X, MARGIN = 1L, FUN = \"table\")\n  print(Y2)\n  stopifnot(identical(Y2, Y1))\n\n  Y0 <- apply(X, MARGIN = 1L, FUN = stats::quantile)\n  Y1 <- future_apply(X, MARGIN = 1L, FUN = stats::quantile)\n  print(Y1)\n  stopifnot(all.equal(Y1, Y0))\n\n  x <- cbind(x1 = 3, x2 = c(4:1, 2:5))\n  names(dimnames(x)) <- c(\"row\", \"col\")\n  x3 <- array(x, dim = c(dim(x), 3),\n              dimnames = c(dimnames(x), list(C = paste0(\"cop.\", 1:3))))\n  \n  y0 <- apply(x, MARGIN = 2L, FUN = identity)\n  stopifnot(identical(y0, x))\n  y1 <- future_apply(x, MARGIN = 2L, FUN = identity)\n  print(y1)\n  stopifnot(identical(y1, y0))\n  \n  y0 <- apply(x3, MARGIN = 2:3, FUN = identity)\n  stopifnot(identical(y0, x3))\n  y1 <- future_apply(x3, MARGIN = 2:3, FUN = identity)\n  print(y1)\n  stopifnot(identical(y1, y0))\n\n  z <- array(1:24, dim = 2:4)\n  y0 <- apply(z, MARGIN = 1:2, FUN = function(x) seq_len(max(x)))\n  y1 <- future_apply(z, MARGIN = 1:2, FUN = function(x) seq_len(max(x)))\n  print(y1)\n  stopifnot(identical(y1, y0))\n\n  message(\"- apply(X, MARGIN = <character>, ...) ...\")\n  X <- matrix(1:2, nrow = 2L, ncol = 1L, dimnames = list(rows = c(\"a\", \"b\")))\n  y0 <- apply(X, MARGIN = \"rows\", FUN = identity)\n  y1 <- future_apply(X, MARGIN = \"rows\", FUN = identity)\n  print(y1)\n  stopifnot(identical(y1, y0))\n\n  message(\"- apply(X, ...) - dim(X) > 2 ...\")\n  X <- array(1:12, dim = c(2, 2, 3))\n  y0 <- apply(X, MARGIN = 1L, FUN = identity)\n  y1 <- future_apply(X, MARGIN = 1L, FUN = identity)\n  print(y1)\n  stopifnot(identical(y1, y0))\n\n  message(\"- apply(X, ...) - not all same names ...\")\n  FUN <- function(x) {\n    if (x[1] == 1L) names(x) <- letters[seq_along(x)]\n    x\n  }\n  X <- matrix(1:4, nrow = 2L, ncol = 2L)\n  y0 <- apply(X, MARGIN = 1L, FUN = FUN)\n  y1 <- future_apply(X, MARGIN = 1L, FUN = FUN)\n  print(y1)\n  stopifnot(identical(y1, y0))\n\n  message(\"- example(future_apply) - reproducible RNG ...\")\n  z1 <- future_apply(X, MARGIN = 1L, FUN = sample,\n          future.seed = 0xBEEF,\n          ## Test also all other 'future.*' arguments\n          future.stdout     = TRUE,\n          future.conditions = NULL,\n          future.globals    = TRUE,\n          future.packages   = NULL,\n          future.scheduling = 1.0,\n          future.chunk.size = NULL,\n          future.label      = \"future_apply-%d\"\n        )\n  print(z1)\n  if (is.null(z0)) {\n    z0 <- z1\n  } else {\n    stopifnot(identical(z1, z0))\n  }\n\n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\n\nmessage(\"*** apply(X, ...) - prod(dim(X)) == 0 [non-parallel] ...\")\nX <- matrix(nrow = 0L, ncol = 2L)\ny0 <- apply(X, MARGIN = 1L, FUN = identity)\ny1 <- future_apply(X, MARGIN = 1L, FUN = identity)\nprint(y1)\nstopifnot(identical(y1, y0))\n  \n\nmessage(\"*** exceptions ...\")\n\n## Error: dim(X) must have a positive length\nres <- tryCatch({\n  y <- future_apply(1L, MARGIN = 1L, FUN = identity)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n## Error: 'X' must have named dimnames\nX <- matrix(1:2, nrow = 2L, ncol = 1L)\nres <- tryCatch({\n  y <- future_apply(X, MARGIN = \"rows\", FUN = identity)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n## Error: not all elements of 'MARGIN' are names of dimensions\nX <- matrix(1:2, nrow = 2L, ncol = 1L, dimnames = list(rows = c(\"a\", \"b\")))\nres <- tryCatch({\n  y <- future_apply(X, MARGIN = \"cols\", FUN = identity)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n\nmessage(\"*** future_apply() ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-future_by.R",
    "content": "#' @tags future_by\n#' @tags listenv\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\nlibrary(listenv)\n\nall_equal_but_call <- function(target, current, ...) {\n  attr(target, \"call\") <- NULL\n  attr(current, \"call\") <- NULL\n  all.equal(target = target, current = current, ...)\n}\n\nmessage(\"*** future_by() ...\")\n\n## ---------------------------------------------------------\n## by()\n## ---------------------------------------------------------\nif (require(\"datasets\") && require(\"stats\")) { ## warpbreaks & lm()\n  ## Use a local variable to test that it is properly exported, because\n  ## 'warpbreaks' is available in all R sessions\n  data <- warpbreaks\n  \n  y0 <- by(data[, 1:2], INDICES = data[,\"tension\"], FUN = summary)\n  y1 <- by(data[, 1], INDICES = data[, -1], FUN = summary, digits = 2L)\n  y2 <- by(data, INDICES = data[,\"tension\"], FUN = function(x, ...) {\n    lm(breaks ~ wool, data = x, ...)\n  }, singular.ok = FALSE)\n  \n  ## now suppose we want to extract the coefficients by group\n  tmp <- with(data, by(data, INDICES = tension, FUN = function(x) {\n    lm(breaks ~ wool, data = x)\n  }))\n  y3 <- sapply(tmp, coef)\n\n  ## Source: {r-source}/tests/reg-tests-1d.R\n  by2 <- function(data, INDICES, FUN) {\n    by(data, INDICES = INDICES, FUN = FUN)\n  }\n  future_by2 <- function(data, INDICES, FUN) {\n    future_by(data, INDICES = INDICES, FUN = FUN)\n  }\n  y4 <- by2(data, INDICES = data[,\"tension\"], FUN = summary)\n\n  for (cores in 1:availCores) {\n    message(sprintf(\"Testing with %d cores ...\", cores))\n    options(mc.cores = cores)\n    strategies <- supportedStrategies(cores)\n  \n    for (strategy in supportedStrategies()) {\n      message(sprintf(\"- plan('%s') ...\", strategy))\n      plan(strategy)\n    \n      y0f <- future_by(data[, 1:2], INDICES = data[,\"tension\"], FUN = summary)\n      stopifnot(all_equal_but_call(y0f, y0, check.attributes = FALSE))\n      \n      y1f <- future_by(data[, 1], INDICES = data[, -1], FUN = summary, digits = 2L)\n      stopifnot(all_equal_but_call(y1f, y1))\n      \n      y2f <- future_by(data, INDICES = data[,\"tension\"], FUN = function(x, ...) {\n        lm(breaks ~ wool, data = x, ...)\n      }, singular.ok = FALSE)\n      stopifnot(all_equal_but_call(y2f, y2))\n      \n      ## now suppose we want to extract the coefficients by group\n      tmp <- with(data, future_by(data, INDICES = tension, FUN = function(x) {\n        lm(breaks ~ wool, data = x)\n      }))\n      y3f <- sapply(tmp, coef)\n      stopifnot(all_equal_but_call(y3f, y3))\n      \n      y4f <- future_by2(data, INDICES = data[,\"tension\"], FUN = summary)\n      stopifnot(all_equal_but_call(y4f, y4))\n\n      ## Defunct /HB 2025-01-11\n      res <- tryCatch({\n        y4f2 <- future_by2(data, INDICES = data[,\"tension\"], FUN = \"summary\")\n      }, error = identity)\n      stopifnot(inherits(res, \"error\"))\n      if (getRversion() >= \"3.6.0\") {\n        stopifnot(inherits(res, \"defunctError\"))\n      }\n    } ## for (strategy ...)\n    \n    message(sprintf(\"Testing with %d cores ... DONE\", cores))\n  } ## for (cores ...)\n} ## if (require(\"stats\"))\n\nmessage(\"*** future_by() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_eapply.R",
    "content": "#' @tags future_eapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_eapply() ...\")\n\nmessage(\"- From example(eapply) ...\")\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n  \n  env <- new.env(hash = FALSE)\n  env$a <- 1:10\n  env$beta <- exp(-3:3)\n  env$logic <- c(TRUE, FALSE, FALSE, TRUE)\n  \n  y0 <- unlist(eapply(env, mean, USE.NAMES = FALSE))\n  y1 <- unlist(future_eapply(env, mean, USE.NAMES = FALSE))\n  stopifnot(all.equal(y1, y0))\n  \n  y0 <- eapply(env, quantile, probs = 1:3/4)\n  y1 <- future_eapply(env, quantile, probs = 1:3/4)\n  stopifnot(all.equal(y1, y0))\n  \n  y0 <- eapply(env, quantile)\n  y1 <- future_eapply(env, quantile)\n  stopifnot(all.equal(y1, y0))\n  y2 <- future_eapply(env, \"quantile\")\n  stopifnot(all.equal(y2, y0))\n\n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\nmessage(\"*** future_eapply() ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-future_kernapply.R",
    "content": "if (require(\"datasets\") && require(\"stats\")) {\n  library(future.apply)\n  library(datasets)\n  \n  plan(multisession)\n  \n  ## Adopted from example(\"kernapply\", package = \"stats\")\n\n  ## ------------------------------------------------------\n  ## Test {future_}kernapply() for 'default'\n  ## ------------------------------------------------------\n  X <- EuStockMarkets[, 1:2]\n  X <- unclass(X)\n  stopifnot(inherits(X, \"matrix\"), !inherits(X, \"ts\"))\n\n  k1 <- kernel(\"daniell\", m = 50L)\n  stopifnot(inherits(k1, \"tskernel\"))\n  X1_truth <- kernapply(X, k = k1)\n  str(X1_truth)\n  X1 <- future_kernapply(X, k = k1)\n  str(X1)\n  stopifnot(identical(X1, X1_truth))\n\n\n  ## ------------------------------------------------------\n  ## Test {future_}kernapply() for 'ts'\n  ## ------------------------------------------------------\n  X <- EuStockMarkets[, 1:2]\n  stopifnot(inherits(X, \"matrix\"), inherits(X, \"ts\"))\n\n  k1 <- kernel(\"daniell\", m = 50L)\n  stopifnot(inherits(k1, \"tskernel\"))\n  X1_truth <- kernapply(X, k = k1)\n  str(X1_truth)\n  X1 <- future_kernapply(X, k = k1)\n  str(X1)\n  stopifnot(identical(X1, X1_truth))\n\n\n  plan(sequential)\n}\n"
  },
  {
    "path": "inst/testme/test-future_lapply,RNG.R",
    "content": "#' @tags future_lapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_lapply() and RNGs ...\")\n\noptions(future.debug = FALSE)\n\nmessage(\"* future_lapply(x, ..., future.seed = <invalid>) ...\")\n\nres <- tryCatch({\n  y <- future_lapply(1:3, FUN = identity, future.seed = as.list(1:2))\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"simpleError\"))\n\nres <- tryCatch({\n  y <- future_lapply(1:3, FUN = identity, future.seed = list(1, 2, 3:4))\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"simpleError\"))\n\nres <- tryCatch({\n  y <- future_lapply(1:3, FUN = identity, future.seed = as.list(1:3))\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"simpleError\"))\n\nseeds <- lapply(1:3, FUN = as_lecyer_cmrg_seed)\nres <- tryCatch({\n  y <- future_lapply(1:3, FUN = identity, future.seed = lapply(seeds, FUN = as.numeric))\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"simpleError\"))\n\nseeds[[1]][1] <- seeds[[1]][1] + 1L\nres <- tryCatch({\n  y <- future_lapply(1:3, FUN = identity, future.seed = seeds)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"simpleError\"))\n\nmessage(\"* future_lapply(x, ..., future.seed = <invalid>) ... DONE\")\n\n\n## Iterate of the same set in all tests\nx <- 1:5\n\nmessage(\"* future_lapply(x, ..., future.seed = FALSE) ...\")\n\ny0 <- y0_nested <- seed00 <- NULL\nfor (cores in 1:availCores) {\n  message(sprintf(\"  - Testing with %d cores ...\", cores))\n  options(mc.cores = cores)\n  \n  for (strategy in supportedStrategies(cores)) {\n    message(sprintf(\"* plan('%s') ...\", strategy))\n    plan(strategy)\n  \n    set.seed(0xBEEF)\n    seed0 <- get_random_seed()\n    y <- future_lapply(x, FUN = function(i) i, future.seed = FALSE)\n    y <- unlist(y)\n    seed <- get_random_seed()\n    if (is.null(y0)) {\n      y0 <- y\n      seed00 <- seed\n    }\n    str(list(y = y))\n    stopifnot(identical(seed, seed0), identical(seed, seed00))\n    ## NOTE: We cannot guarantee the same random numbers, because\n    ## future.seed = FALSE.\n    \n    message(sprintf(\"* plan('%s') ... DONE\", strategy))\n  }  ## for (strategy ...)\n  message(sprintf(\"  - Testing with %d cores ... DONE\", cores))\n} ## for (core ...)\n\nmessage(\"* future_lapply(x, ..., future.seed = FALSE) ... DONE\")\n\n\nseed_sets <- list(\n  A = TRUE,\n##  B = NA,\n  C = 42L,\n  D = as_lecyer_cmrg_seed(42L),\n  E = list(),\n  F = vector(\"list\", length = length(x)),\n  G = NULL\n)\n\n## Generate sequence of seeds of the current RNGkind()\n## NOTE: This is NOT a good way to generate random seeds!!!\nseeds <- lapply(seq_along(x), FUN = function(i) {\n  set.seed(i)\n  globalenv()$.Random.seed\n})\nseed_sets$E <- seeds\n\n## Generate sequence of L'Ecyer CMRG seeds\nseeds <- seed_sets$F\nseeds[[1]] <- seed_sets$D\nfor (kk in 2:length(x)) seeds[[kk]] <- parallel::nextRNGStream(seeds[[kk - 1]])\nseed_sets$F <- seeds\nseed_sets$G <- seed_sets$A\n\nrm(list = \"seeds\")\n\nfor (name in names(seed_sets)) {\n  future.seed <- seed_sets[[name]]\n\n  if (is.list(future.seed)) {\n    label <- sprintf(\"<list of %d seeds each being a %d-int seed>\",\n                     length(future.seed), length(future.seed[[1]]))\n  } else {\n    label <- hpaste(future.seed)\n  }\n  message(sprintf(\"* future_lapply(x, ..., future.seed = %s) ...\", label))\n  \n  set.seed(0xBEEF)\n  y0 <- seed00 <- NULL\n\n  for (cores in 1:availCores) {\n    message(sprintf(\"  - Testing with %d cores ...\", cores))\n    options(mc.cores = cores)\n  \n    for (strategy in supportedStrategies(cores)) {\n      message(sprintf(\"* plan('%s') ...\", strategy))\n      plan(strategy)\n      \n      set.seed(0xBEEF)\n      seed0 <- get_random_seed()\n      y <- future_lapply(x, FUN = function(i) {\n        rnorm(1L)\n      }, future.seed = future.seed)\n      y <- unlist(y)\n      seed <- get_random_seed()\n      if (is.null(y0)) {\n        y0 <- y\n        seed00 <- seed\n      }\n      str(list(y = y))\n      stopifnot(!identical(seed, seed0), identical(seed, seed00),\n                identical(y, y0))\n  \n      ## RNG-based results should also be identical regardless of\n      ## load-balance scheduling.\n      for (scheduling in list(FALSE, TRUE, 0, 0.5, 2.0, Inf)) {\n        set.seed(0xBEEF)\n        seed0 <- get_random_seed()\n        y <- future_lapply(x, FUN = function(i) {\n          rnorm(1L)\n        }, future.seed = future.seed, future.scheduling = scheduling)\n        seed <- get_random_seed()\n        y <- unlist(y)\n        str(list(y = y))\n        stopifnot(!identical(seed, seed0), identical(seed, seed00),\n                  identical(y, y0))\n      }\n  \n      ## Nested future_lapply():s\n      for (scheduling in list(FALSE, TRUE)) {\n        y <- future_lapply(x, FUN = function(i) {\n          .seed <- globalenv()$.Random.seed\n          \n          z <- future_lapply(1:3, FUN = function(j) {\n            list(j = j, seed = globalenv()$.Random.seed)\n          }, future.seed = .seed)\n    \n          ## Assert that all future seeds are unique\n          seeds <- lapply(z, FUN = function(x) x$seed)\n          for (kk in 2:length(seeds)) stopifnot(!all(seeds[[kk]] == seeds[[1]]))\n          \n          list(i = i, seed = .seed, sample = rnorm(1L), z = z)\n        }, future.seed = 42L, future.scheduling = scheduling)\n  \n        if (is.null(y0_nested)) y0_nested <- y\n        str(list(y = y))\n    \n        ## Assert that all future seeds (also nested ones) are unique\n        seeds <- Reduce(c, lapply(y, FUN = function(x) {\n          c(list(seed = x$seed), lapply(x$z, FUN = function(x) x$seed))\n        }))\n        for (kk in 2:length(seeds)) stopifnot(!all(seeds[[kk]] == seeds[[1]]))\n        \n        stopifnot(identical(y, y0_nested))\n      }\n      \n      message(sprintf(\"* plan('%s') ... DONE\", strategy))\n    } ## for (strategy ...)\n    message(sprintf(\"  - Testing with %d cores ... DONE\", cores))\n  } ## for (cores ...)\n  \n  message(sprintf(\"* future_lapply(x, ..., future.seed = %s) ... DONE\", label))\n\n} ## for (name ...)\n\n\nmessage(\"*** future_lapply() and RNGs ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-future_lapply,globals.R",
    "content": "#' @tags future_lapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\nlibrary(tools) ## toTitleCase()\n\noptions(future.debug = FALSE)\noptions(future.apply.debug = TRUE)\n\nmessage(\"*** future_lapply() - globals ...\")\n\nplan(cluster, workers = \"localhost\")\n\na <- 1\nb <- 2\n\nglobals_set <- list(\n  A = FALSE,\n  B = TRUE,\n  C = c(\"a\", \"b\"),\n  D = list(a = 2, b = 3)\n)\n\nx <- list(1)\ny_truth <- list(A = NULL, B = list(1), C = list(1), D = list(2))\nstr(y_truth)\n\nfor (name in names(globals_set)) {\n  globals <- globals_set[[name]]\n  message(\"Globals set \", sQuote(name))\n  y <- tryCatch({\n    future_lapply(x, FUN = function(x) {\n      median(c(x, a, b))\n    }, future.globals = globals, future.packages = \"utils\")\n  }, error = identity)\n  print(y)\n  stopifnot((name == \"A\" && inherits(y, \"error\")) || \n             identical(y, y_truth[[name]]))\n}\n\nmessage(\"*** future_lapply() - globals ... DONE\")\n\n\nmessage(\"*** future_lapply() - manual globals ...\")\n\nd <- 42\ny <- future_lapply(1:2, FUN = function(x) { x * d },\n                   future.globals = structure(FALSE, add = \"d\"))\nstopifnot(identical(y, list(42, 84)))\n\ne <- 42\nres <- tryCatch({\n  future_lapply(1:2, FUN = function(x) { 2 * e },\n                future.globals = structure(TRUE, ignore = \"e\"))\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nmessage(\"*** future_lapply() - manual globals ... DONE\")\n\n\n\n## Test adopted from http://stackoverflow.com/questions/42561088/nested-do-call-within-a-foreach-dopar-environment-cant-find-function-passed-w\n\nmessage(\"*** future_lapply() - tricky globals ...\")\n\nmy_add <- function(a, b) a + b\n\ncall_my_add <- function(a, b) {\n  do.call(my_add, args = list(a = a, b = b))\n}\n\ncall_my_add_caller <- function(a, b, FUN = call_my_add) {\n  do.call(FUN, args = list(a = a, b = b))\n}\n\nmain <- function(x = 1:2, caller = call_my_add_caller,\n                 args = list(FUN = call_my_add)) {\n  results <- future_lapply(x, FUN = function(i) {\n    do.call(caller, args = c(list(a = i, b = i + 1L), args))\n  })\n  results\n}\n\nx <- list(list(1:2))\nz_length <- lapply(x, FUN = do.call, what = length)\nfun <- function(...) sum(...)\nz_fun <- lapply(x, FUN = do.call, what = fun)\n\ny0 <- NULL\nfor (strategy in supportedStrategies()) {\n  plan(strategy)\n\n  y <- main(1:3)\n  if (is.null(y0)) y0 <- y\n  stopifnot(identical(y, y0))\n\n  message(\"- future_lapply(x, FUN = do.call, ...) ...\")\n  z <- future_lapply(x, FUN = do.call, what = length)\n  stopifnot(identical(z, z_length))\n  z <- future_lapply(x, FUN = do.call, what = fun)\n  stopifnot(identical(z, z_fun))\n\n  message(\"- future_lapply(x, ...) - passing arguments via '...' ...\")\n  ## typeof() == \"list\"\n  obj <- data.frame(a = 1:2)\n  stopifnot(typeof(obj) == \"list\")\n  y <- future_lapply(1L, function(a, b) typeof(b), b = obj)\n  stopifnot(identical(y[[1]], typeof(obj)))\n\n  ## typeof() == \"environment\"\n  obj <- new.env()\n  stopifnot(typeof(obj) == \"environment\")\n  y <- future_lapply(1L, function(a, b) typeof(b), b = obj)\n  stopifnot(identical(y[[1]], typeof(obj)))\n\n  ## typeof() == \"S4\"\n  if (requireNamespace(\"methods\")) {\n    obj <- methods::getClass(\"MethodDefinition\")\n    stopifnot(typeof(obj) == \"S4\")\n    y <- future_lapply(1L, function(a, b) typeof(b), b = obj)\n    stopifnot(identical(y[[1]], typeof(obj)))\n  }\n\n  message(\"- future_lapply(X, ...) - 'X' containing globals ...\")\n  ## From https://github.com/futureverse/future.apply/issues/12\n  a <- 42\n  b <- 21\n  X <- list(\n    function(b) 2 * a,\n    function() b / 2,\n    function() a + b,\n    function() nchar(toTitleCase(\"hello world\"))\n  )\n  z0 <- lapply(X, FUN = function(f) f())\n  str(z0)\n  z1 <- future_lapply(X, FUN = function(f) f())\n  str(z1)\n  stopifnot(identical(z1, z0))\n\n#  message(\"- future_lapply(x, ...) - passing '...' as a global ...\")\n#  ## https://github.com/futureverse/future/issues/417\n#  fcn0 <- function(...) { lapply(1, FUN = function(x) list(...)) }\n#  z0 <- fcn0(a = 1)\n#  str(list(z0 = z0))\n#  stopifnot(identical(z0, list(list(a = 1))))\n#  fcn <- function(...) { future_lapply(1, FUN = function(x) list(...)) }\n#  z1 <- fcn(a = 1)\n#  str(list(z1 = z1))\n#  stopifnot(identical(z1, z0))\n\n  ## https://github.com/futureverse/future.apply/issues/47\n  message(\"- future_lapply(X, ...) - '{ a <- a + 1; a }' ...\")\n  a <- 1\n  z0 <- lapply(1, function(ii) {\n    a <- a + 1\n    a\n  })\n  z1 <- future_lapply(1, function(ii) {\n    a <- a + 1\n    a\n  })\n  stopifnot(identical(z1, z0))\n\n  ## https://github.com/futureverse/future.apply/issues/47\n  message(\"- future_lapply(X, ...) - '{ a; a <- a + 1 }' ...\")\n  z2 <- tryCatch(future_lapply(1, function(ii) {\n    a\n    a <- a + 1\n  }), error = identity)\n  stopifnot(identical(z2, z0))\n\n  ## https://github.com/futureverse/future.apply/issues/85\n  message(\"- future_lapply(..., future.globals = <list>) ...\")\n  a <- 0\n  y <- future_lapply(1, FUN = function(x) a, future.globals = list(a = 42))\n  str(y)\n  stopifnot(y[[1]] == 42)\n} ## for (strategy ...)\n\nmessage(\"*** future_lapply() - tricky globals ... DONE\")\n\n\nmessage(\"*** future_lapply() - missing arguments ...\")\n\n## Here 'abc' becomes missing, i.e. missing(abc) is TRUE\nfoo <- function(x, abc) future_lapply(x, FUN = function(y) y)\ny <- foo(1:2)\nstopifnot(identical(y, as.list(1:2)))\n\nmessage(\"*** future_lapply() - missing arguments ... DONE\")\n\n\nmessage(\"*** future_lapply() - false positives ...\")\n\n## Here 'abc' becomes a promise, which fails to resolve\n## iff 'xyz' does not exist. (Issue #161)\nsuppressWarnings(rm(list = \"xyz\"))\nfoo <- function(x, abc) future_lapply(x, FUN = function(y) y)\ny <- foo(1:2, abc = (xyz >= 3.14))\nstopifnot(identical(y, as.list(1:2)))\n\nmessage(\"*** future_lapply() - false positives ... DONE\")\n\n\nmessage(\"*** future_lapply() - too large ...\")\n\noMaxSize <- getOption(\"future.globals.maxSize\")\nX <- replicate(10L, 1:100, simplify = FALSE)\nFUN <- function(x) {\n  getOption(\"future.globals.maxSize\")\n}\n\ny0 <- lapply(X, FUN = FUN)\nstopifnot(all(sapply(y0, FUN = identical, oMaxSize)))\n\nsizes <- unclass(c(FUN = object.size(FUN), X = object.size(X)))\ncat(sprintf(\"Baseline size of globals: %.2f KiB\\n\", sizes[[\"FUN\"]] / 1024))\n\nmessage(\"- true positive ...\")\noptions(future.globals.maxSize = 1L)\nres <- tryCatch({\n  y <- future_lapply(X, FUN = FUN)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\nres <- NULL\noptions(future.globals.maxSize = oMaxSize)\n\nmaxSize <- getOption(\"future.globals.maxSize\")\ny <- future_lapply(X, FUN = FUN)\nstr(y)\nstopifnot(all(sapply(y, FUN = identical, oMaxSize)))\n\nmessage(\"- approximately invariant to chunk size ...\")\nmaxSize <- sizes[[\"FUN\"]] + sizes[[\"X\"]] / length(X)\noptions(future.globals.maxSize = maxSize)\n\nfor (chunk.size in c(1L, 2L, 5L, 10L)) {\n  y <- future_lapply(X, FUN = FUN, future.chunk.size = chunk.size)\n  str(y)\n  stopifnot(all(unlist(y) == maxSize))\n  cat(sprintf(\"maxSize = %g bytes\\nfuture.globals.maxSize = %g bytes\\n\",\n              maxSize, getOption(\"future.globals.maxSize\")))\n  stopifnot(getOption(\"future.globals.maxSize\") == maxSize)\n}\ny <- NULL\noptions(future.globals.maxSize = oMaxSize)\n\n\nmessage(\"*** future_lapply() - too large ... DONE\")\n\n\nmessage(\"*** future_lapply() - globals exceptions ...\")\n\nres <- tryCatch({\n  y <- future_lapply(1, FUN = function(x) x, future.globals = 42)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nres <- tryCatch({\n  y <- future_lapply(1, FUN = function(x) x, future.globals = list(1))\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nres <- tryCatch({\n  y <- future_lapply(1, FUN = function(x) x, future.globals = \"...future.FUN\")\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nres <- tryCatch({\n  y <- future_lapply(1, FUN = function(x) x, future.globals = \"...future.FUN\")\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n...future.elements_ii <- 42L\nX <- list(function() 2 * ...future.elements_ii)\nres <- tryCatch({\n  y <- future_lapply(X, FUN = function(f) f())\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nmessage(\"*** future_lapply() - globals exceptions ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-future_lapply.R",
    "content": "#' @tags future_lapply\n#' @tags listenv\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\nlibrary(listenv)\n\nmessage(\"*** future_lapply() ...\")\n\nx_a <- list(a = \"integer\", b = \"numeric\", c = \"character\", c = \"list\")\nstr(list(x_a = x_a))\ny_a <- lapply(x_a, FUN = base::vector, length = 2L)\nstr(list(y_a = y_a))\n\nx_b <- list(a = c(\"hello\", b = 1:100))\nstr(list(x_b = x_b))\ny_b <- lapply(x_b, FUN = future:::hpaste, collapse = \"; \", maxHead = 3L)\nstr(list(y_b = y_b))\n\nx_c <- list()\ny_c <- listenv()\ny_c$A <- 3L\nx_c$a <- y_c\ny_c<- listenv()\ny_c$A <- 3L\ny_c$B <- c(\"hello\", b = 1:100)\nx_c$b <- y_c\nprint(x_c)\ny_c <- lapply(x_c, FUN = listenv::mapping)\nstr(list(y_c = y_c))\n\nfor (cores in 1:availCores) {\n  message(sprintf(\"Testing with %d cores ...\", cores))\n  options(mc.cores = cores)\n  strategies <- supportedStrategies(cores)\n\n  for (strategy in supportedStrategies()) {\n    message(sprintf(\"- plan('%s') ...\", strategy))\n    plan(strategy)\n\n    for (scheduling in list(FALSE, TRUE, structure(TRUE, ordering = \"random\"), structure(TRUE, ordering = function(n) rev(seq_len(n))))) {\n      message(\"- future_lapply(x, FUN = vector, ...) ...\")\n      y <- future_lapply(x_a, FUN = vector, length = 2L, future.scheduling = scheduling)\n      str(list(y = y))\n      stopifnot(identical(y, y_a))\n\n      y <- future_lapply(x_a, FUN = \"vector\", length = 2L, future.scheduling = scheduling)\n      str(list(y = y))\n      stopifnot(identical(y, y_a))\n\n      message(\"- future_lapply(x, FUN = base::vector, ...) ...\")\n      y <- future_lapply(x_a, FUN = base::vector, length = 2L, future.scheduling = scheduling)\n      str(list(y = y))\n      stopifnot(identical(y, y_a))\n\n      message(\"- future_lapply(x, FUN = future:::hpaste, ...) ...\")\n      y <- future_lapply(x_b, FUN = future:::hpaste, collapse = \"; \", maxHead = 3L, future.scheduling = scheduling)\n      str(list(y = y))\n      stopifnot(identical(y, y_b))\n\n      message(\"- future_lapply(x, FUN = listenv::listenv, ...) ...\")\n      y <- future_lapply(x_c, FUN = listenv::mapping, future.scheduling = scheduling)\n      str(list(y = y))\n      stopifnot(identical(y, y_c))\n    } ## for (scheduling ...)\n\n    message(\"- future_lapply(x, FUN, ...) for large length(x) ...\")\n    a <- 3.14\n    x_d <- 1:1e4\n    y <- future_lapply(x_d, FUN = function(z) sqrt(z + a))\n    y <- unlist(y, use.names = FALSE)\n    stopifnot(all.equal(y, sqrt(x_d + a)))\n\n    message(\"- future_lapply(x, FUN = table, ...) ...\")\n    x <- list(a = 1:4, b = 5:8)\n    y0 <- lapply(x, FUN = table)\n    y1 <- future_lapply(x, FUN = table)\n    stopifnot(all.equal(y1, y0, check.attributes = FALSE)) ## FIXME\n\n    message(\"- future_lapply(x, ...) where length(x) != length(as.list(x)) ...\")\n    x <- structure(list(a = 1, b = 2), class = \"Foo\")\n    as.list.Foo <- function(x, ...) c(x, c = 3)\n    y0 <- lapply(x, FUN = length)\n    stopifnot(identical(y0, list(a = 1L, b = 1L, c = 1L)))\n    y1 <- future_lapply(x, FUN = length)\n    stopifnot(identical(y1, y0))\n    rm(list = \"as.list.Foo\")\n    \n    message(\"- future_lapply(x, ...) where x[[i]] subsets via S3 method ...\")\n    x <- structure(list(a = 1, b = 2), class = \"Foo\")\n    `[[.Foo` <- function(x, ...) 0\n    y0 <- lapply(x, FUN = identity)\n    stopifnot(identical(y0, list(a = 0, b = 0)))\n    y1 <- future_lapply(x, FUN = identity)\n    if (getOption(\"future.apply.chunkWith\", \"[[\") == \"[\") {\n      stopifnot(identical(y1, unclass(x)))\n    } else {\n      stopifnot(identical(y1, y0))\n    }\n    rm(list = \"[[.Foo\")\n} ## for (strategy ...)\n\n  message(sprintf(\"Testing with %d cores ... DONE\", cores))\n} ## for (cores ...)\n\n\nmessage(\"*** future_lapply() - special cases ...\")\n\nX <- list()\nnames(X) <- character(0L)\ny <- future_lapply(X, FUN = identity)\nstopifnot(length(y) == 0L, !is.null(names(y)), identical(y, X))\n\nX <- character(0L)\ny0 <- lapply(X, FUN = identity)\ny <- future_lapply(X, FUN = identity)\nstopifnot(identical(y, y0))\n\nX <- character(0L)\nnames(X) <- character(0L)\ny0 <- lapply(X, FUN = identity)\ny <- future_lapply(X, FUN = identity)\nstopifnot(identical(y, y0))\n\nmessage(\"*** future_lapply() - special cases ... DONE\")\n\n\nmessage(\"*** future_lapply() - exceptions ...\")\n\nres <- tryCatch({\n  future_lapply(1:3, FUN = identity, future.chunk.size = structure(1L, ordering = \"invalid\"))\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nmessage(\"*** future_lapply() - exceptions ... DONE\")\n\nmessage(\"*** future_lapply() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_mapply,globals.R",
    "content": "#' @tags future_mapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\nlibrary(tools) ## toTitleCase()\n\nmessage(\"*** future_mapply() - globals ...\")\n\n#plan(cluster, workers = \"localhost\")\nplan(sequential)\n\noptions(future.debug = FALSE)\na <- 1\nb <- 2\n\nglobals_set <- list(\n  A = FALSE,\n  B = TRUE,\n  C = c(\"a\", \"b\"),\n  D = list(a = 1, b = 2)\n)\n\nx <- list(1)\n\nfor (name in names(globals_set)) {\n  globals <- globals_set[[name]]\n  message(\"Globals set \", sQuote(name))\n  str(globals)\n  \n  y_truth <- tryCatch({\n    mapply(function(x) {\n      median(c(x, a, b))\n    }, x)\n  }, error = identity)\n\n  y1 <- tryCatch({\n    future_mapply(function(x) {\n      median(c(x, a, b))\n    }, x)\n  }, error = identity)\n  print(y1)\n  stopifnot(identical(y1, y_truth))\n\n  y2 <- tryCatch({\n    future_mapply(function(x) {\n      median(c(x, a, b))\n    }, x, future.globals = globals, future.packages = \"utils\")\n  }, error = identity)\n  print(y2)\n  stopifnot(identical(y2, y_truth))\n}\n\nmessage(\"*** future_mapply() - globals ... DONE\")\n\n\n\n## Test adopted from http://stackoverflow.com/questions/42561088/nested-do-call-within-a-foreach-dopar-environment-cant-find-function-passed-w\n\nmessage(\"*** future_mapply() - tricky globals ...\")\n\nmy_add <- function(a, b) a + b\n\ncall_my_add <- function(a, b) {\n  do.call(my_add, args = list(a = a, b = b))\n}\n\ncall_my_add_caller <- function(a, b, FUN = call_my_add) {\n  do.call(FUN, args = list(a = a, b = b))\n}\n\nmain <- function(x = 1:2, caller = call_my_add_caller,\n                 args = list(FUN = call_my_add)) {\n  results <- future_mapply(function(i) {\n    do.call(caller, args = c(list(a = i, b = i + 1L), args))\n  }, x)\n  results\n}\n\nx <- list(list(1:2))\nz_length <- mapply(do.call, args = x, MoreArgs = list(what = length))\nfun <- function(...) sum(...)\nz_fun <- mapply(do.call, args = x, MoreArgs = list(what = fun))\n\ny0 <- NULL\nfor (strategy in supportedStrategies()) {\n  plan(strategy)\n\n  y <- main(1:3)\n  if (is.null(y0)) y0 <- y\n  stopifnot(identical(y, y0))\n\n  message(\"- future_mapply(do.call, x, ...) ...\")\n  z <- future_mapply(do.call, args = x, MoreArgs = list(what = length))\n  stopifnot(identical(z, z_length))\n  z <- future_mapply(do.call, args = x, MoreArgs = list(what = fun))\n  stopifnot(identical(z, z_fun))\n\n  message(\"- future_mapply(FUN, x, ...) - passing arguments via '...' ...\")\n  ## typeof() == \"list\"\n  obj <- data.frame(a = 1:2)\n  stopifnot(typeof(obj) == \"list\")\n  y <- future_mapply(function(a, b) typeof(b), 1L, MoreArgs = list(b = obj))\n  stopifnot(identical(y[[1]], typeof(obj)))\n\n  ## typeof() == \"environment\"\n  obj <- new.env()\n  stopifnot(typeof(obj) == \"environment\")\n  y <- future_mapply(function(a, b) typeof(b), 1L, MoreArgs = list(b = obj))\n  stopifnot(identical(y[[1]], typeof(obj)))\n\n  ## typeof() == \"S4\"\n  if (requireNamespace(\"methods\")) {\n    obj <- methods::getClass(\"MethodDefinition\")\n    stopifnot(typeof(obj) == \"S4\")\n    y <- future_mapply(function(a, b) typeof(b), 1L, MoreArgs = list(b = obj))\n    stopifnot(identical(y[[1]], typeof(obj)))\n  }\n\n  message(\"- future_mapply(FUN, X, ...) - 'X' containing globals ...\")\n  ## From https://github.com/futureverse/future.apply/issues/12\n  a <- 42\n  b <- 21\n  X <- list(\n    function(b) 2 * a,\n    function() b / 2,\n    function() a + b,\n    function() nchar(toTitleCase(\"hello world\"))\n  )\n  z0 <- mapply(function(s, f) f() + s, s = seq_along(X), X)\n  str(z0)\n  z1 <- future_mapply(function(s, f) f() + s, s = seq_along(X), X)\n  str(z1)\n  stopifnot(identical(z1, z0))\n}\n\nmessage(\"*** future_mapply() - tricky globals ... DONE\")\n\n\nmessage(\"*** future_mapply() - missing arguments ...\")\n\n## Here 'abc' becomes missing, i.e. missing(abc) is TRUE\nfoo <- function(x, abc) mapply(function(y) y, x)\ny0 <- foo(1:2)\nfoo <- function(x, abc) future_mapply(function(y) y, x)\ny <- foo(1:2)\nstopifnot(identical(y, y0))\n\nmessage(\"*** future_mapply() - missing arguments ... DONE\")\n\n\nmessage(\"*** future_mapply() - false positives ...\")\n\n## Here 'abc' becomes a promise, which fails to resolve\n## iff 'xyz' does not exist. (Issue #161)\nsuppressWarnings(rm(list = \"xyz\"))\nfoo <- function(x, abc) mapply(function(y) y, x)\ny0 <- foo(1:2, abc = (xyz >= 3.14))\nfoo <- function(x, abc) future_mapply(function(y) y, x)\ny <- foo(1:2, abc = (xyz >= 3.14))\nstopifnot(identical(y, y0))\n\nmessage(\"*** future_mapply() - false positives ... DONE\")\n\n\nmessage(\"*** future_mapply() - too large ...\")\n\nX <- replicate(10L, 1:100, simplify = FALSE)\nFUN <- function(x) {\n  getOption(\"future.globals.maxSize\")\n}\n\ny0 <- mapply(FUN = FUN, X)\n\nsizes <- unclass(c(FUN = object.size(FUN), X = object.size(X)))\ncat(sprintf(\"Baseline size of globals: %.2f KiB\\n\", sizes[[\"FUN\"]] / 1024))\n\nmessage(\"- true positive ...\")\noMaxSize <- getOption(\"future.globals.maxSize\")\noptions(future.globals.maxSize = 1L)\nres <- tryCatch({\n  y <- future_mapply(FUN = FUN, X)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\nres <- NULL\noptions(future.globals.maxSize = oMaxSize)\n\nmaxSize <- getOption(\"future.globals.maxSize\")\ny <- future_mapply(FUN = FUN, X)\nstr(y)\nstopifnot(all(sapply(y, FUN = identical, oMaxSize)))\n\nmessage(\"- approximately invariant to chunk size ...\")\nmaxSize <- sizes[[\"FUN\"]] + sizes[[\"X\"]] / length(X)\nmaxSize <- 4.0 * maxSize  ## Add a bit of leeway\noptions(future.globals.maxSize = maxSize)\n\nfor (chunk.size in c(1L, 2L, 5L, structure(10L, ordering = \"random\"))) {\n  y <- future_mapply(FUN = FUN, X, future.chunk.size = chunk.size)\n  str(y)\n  stopifnot(all(unlist(y) == maxSize))\n  cat(sprintf(\"maxSize = %g bytes\\nfuture.globals.maxSize = %g bytes\\n\",\n              maxSize, getOption(\"future.globals.maxSize\")))\n  stopifnot(getOption(\"future.globals.maxSize\") == maxSize)\n}\ny <- NULL\noptions(future.globals.maxSize = oMaxSize)\n\nmessage(\"*** future_mapply() - too large ... DONE\")\n\n\nmessage(\"*** future_mapply() - globals exceptions ...\")\n\nres <- tryCatch({\n  y <- future_mapply(function(x) x, 1, future.globals = 42)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nres <- tryCatch({\n  y <- future_mapply(function(x) x, 1, future.globals = list(1))\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nres <- tryCatch({\n  y <- future_mapply(function(x) x, 1, future.globals = \"...future.FUN\")\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n...future.elements_ii <- 42L\nX <- list(function() 2 * ...future.elements_ii)\nres <- tryCatch({\n  y <- future_mapply(FUN = function(f) f(), X)\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nmessage(\"*** future_mapply() - globals exceptions ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-future_mapply.R",
    "content": "#' @tags future_mapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_mapply() ...\")\n\nmessage(\"- Parallel RNG truth (for later)...\")\nplan(sequential)\ny_rng_0 <- future_mapply(stats::runif, n = 1:4, max = 2:5,\n                         MoreArgs = list(min = 1), future.seed = 0xBEEF)\nprint(y_rng_0)\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n\n  message(\"- From example(mapply) ...\")\n  y0 <- mapply(rep, 1:4, 4:1)\n  y1 <- future_mapply(rep, 1:4, 4:1)\n  stopifnot(identical(y1, y0))\n  y2 <- future_mapply(\"rep\", 1:4, 4:1)\n  stopifnot(identical(y2, y0))\n  \n  y0 <- mapply(rep, times = 1:4, x = 4:1)\n  y1 <- future_mapply(rep, times = 1:4, x = 4:1)\n  stopifnot(identical(y1, y0))\n  \n  y0 <- mapply(rep, times = 1:4, MoreArgs = list(x = 42))\n  y1 <- future_mapply(rep, times = 1:4, MoreArgs = list(x = 42))\n  stopifnot(identical(y1, y0))\n  \n  y0 <- mapply(function(x, y) seq_len(x) + y,\n               c(a =  1, b = 2, c = 3),  # names from first\n               c(A = 10, B = 0, C = -10))\n  y1 <- future_mapply(function(x, y) seq_len(x) + y,\n                      c(a =  1, b = 2, c = 3),  # names from first\n                      c(A = 10, B = 0, C = -10))\n  stopifnot(identical(y1, y0))\n\n  message(\"- future_.mapply()\")\n  dots <- list(c(a =  1, b = 2, c = 3),  # names from first\n               c(A = 10, B = 0, C = -10))\n  y2 <- .mapply(function(x, y) seq_len(x) + y, dots = dots, MoreArgs = list())\n  names(y0) <- NULL  ## .mapply() don't set names\n  stopifnot(all.equal(y2, y0))\n  y3 <- future_.mapply(function(x, y) seq_len(x) + y, dots = dots, MoreArgs = list())\n  stopifnot(all.equal(y3, y2))\n\n  word <- function(C, k) paste(rep.int(C, k), collapse = \"\")\n  for (chunk.size in list(1L, structure(2L, ordering = \"random\"), structure(3L, ordering = 5:1))) {\n    y0 <- mapply(word, LETTERS[1:5], 5:1, SIMPLIFY = FALSE)\n    y1 <- future_mapply(word, LETTERS[1:5], 5:1, SIMPLIFY = FALSE, future.chunk.size = chunk.size)\n    stopifnot(identical(y1, y0))\n\n    dots <- list(LETTERS[1:5], 5:1)\n    MoreArgs <- list()\n    y2 <- .mapply(word, dots = dots, MoreArgs = list())\n    names(y0) <- NULL  ## .mapply() don't set names\n    stopifnot(all.equal(y2, y0))\n    y3 <- future_.mapply(word, dots = dots, MoreArgs = list())\n    stopifnot(all.equal(y3, y2))\n  }\n\n  message(\"- Subsetting (Issue #17) ...\")\n  X <- as.Date(\"2018-06-01\")\n  y0 <- mapply(FUN = identity, X, SIMPLIFY = FALSE)\n  y1 <- future_mapply(FUN = identity, X, SIMPLIFY = FALSE)\n  stopifnot(identical(y1, y0))\n\n  dots <- list(X)\n  y2 <- .mapply(FUN = identity, dots = dots, MoreArgs = MoreArgs)\n  stopifnot(identical(y2, y0))\n  y3 <- future_.mapply(FUN = identity, dots = dots, MoreArgs = MoreArgs)\n  stopifnot(identical(y3, y2))\n\n  message(\"- Non-recycling of MoreArgs (Issue #51) ...\")\n  y0 <- base::mapply(\n    function(x, y) y,\n    x = 1:2, MoreArgs = list(y = 3:4)\n  )\n  y1 <- future.apply::future_mapply(\n    function(x, y) y,\n    x = 1:2, MoreArgs = list(y = 3:4),\n    future.seed = FALSE\n  )\n  stopifnot(identical(y1, y0))\n  y2 <- future.apply::future_mapply(\n    function(x, y) y,\n    x = 1:2, MoreArgs = list(y = 3:4),\n    future.seed = TRUE\n  )\n  stopifnot(identical(y2, y0))\n\n  dots <- list(x = 1:2)\n  MoreArgs <- list(y = 3:4)\n  y3 <- .mapply(function(x, y) y, dots = dots, MoreArgs = MoreArgs)\n  y4 <- future_.mapply(function(x, y) y, dots = dots, MoreArgs = MoreArgs)\n  stopifnot(identical(y4, y3))\n\n  message(\"- Recycle arguments to same length ...\")\n  y0 <- mapply(rep, 1:4, 2:1)\n  y1 <- future_mapply(rep, 1:4, 2:1)\n  stopifnot(identical(y1, y0))\n\n  \n  message(\"- Parallel RNG ...\")\n  y_rng_1 <- future_mapply(stats::runif, n = 1:4, max = 2:5,\n                           MoreArgs = list(min = 1), future.seed = 0xBEEF)\n  print(y_rng_1)\n  stopifnot(all.equal(y_rng_1, y_rng_0))\n\n  message(\"- future_Map() ...\")\n  xs <- replicate(5, stats::runif(10), simplify = FALSE)\n  ws <- replicate(5, stats::rpois(10, 5) + 1, simplify = FALSE)\n  y0 <- Map(weighted.mean, xs, ws)\n  y1 <- future_Map(stats::weighted.mean, xs, ws)\n  stopifnot(all.equal(y1, y0))\n\n  message(\"- future_mapply() - 'max-or-0-if' recycling rule ...\")\n  ## R (>= 4.2.0): mapply() & Map() follow usual \"max-or-0-if\" recycling rule\n  ## and keeps returning a named list in the \"empty\" case.\n  \n  truth <- list()\n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(`+`, 1:3, NULL)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(`+`, 1:3, NULL)\n  stopifnot(identical(y, truth))\n  \n  truth <- setNames(list(), character())\n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, character(), NULL)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, character(), NULL)\n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, character(), letters)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, character(), letters)\n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, \"A\", character())\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, \"A\", character())\n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, character(), letters) \n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, character(), letters) \n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, character(), NULL)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, character(), NULL)\n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, character(), letters)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, character(), letters)\n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, \"A\", character()) \n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, \"A\", character()) \n  stopifnot(identical(y, truth))\n  \n  if (getRversion() >= \"4.2.0\") {\n    y0 <- mapply(paste, character(), letters) \n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, character(), letters) \n  stopifnot(identical(y, truth))\n\n  ## Gives an error in R-devel (2021-11-26 r81252)\n  if (getRversion() >= \"4.2.0\" && FALSE) {\n    y0 <- mapply(paste, c(a = \"A\"), character())\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_mapply(paste, c(a = \"A\"), character())\n  stopifnot(identical(y, truth))\n\n  ## R (>= 4.2.0): Map() now recycles similar to basic Ops:\n  truth <- as.list(1 + 1:3)\n  if (getRversion() >= \"4.2.0\") {\n    y0 <- Map(`+`, 1, 1:3)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_Map(`+`, 1, 1:3)\n  stopifnot(identical(y, truth))\n  \n  truth <- as.list(numeric() + 1:3)\n  if (getRversion() >= \"4.2.0\") {\n    y0 <- Map(`+`, numeric(), 1:3)\n    stopifnot(identical(y0, truth))\n  }\n  y <- future_Map(`+`, numeric(), 1:3)\n  stopifnot(identical(y, truth))\n\n  message(\"- future_mapply(x, ...) where x[[i]] subsets via S3 method ...\")\n  x <- structure(list(a = 1, b = 2), class = \"Foo\")\n  `[[.Foo` <- function(x, ...) 0\n  y0 <- mapply(x, FUN = identity)\n  stopifnot(identical(y0, c(a = 0, b = 0)))\n  y1 <- future_mapply(x, FUN = identity)\n  if (getOption(\"future.apply.chunkWith\", \"[[\") == \"[\") {\n    stopifnot(identical(y1, unlist(x)))\n  } else {\n    stopifnot(identical(y1, y0))\n  }\n\n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\nmessage(\"- Empty input [non parallel] ...\")\ny0 <- mapply(search)\ny1 <- future_mapply(search)\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(list, integer(0L))\ny1 <- future_mapply(list, integer(0L))\nstopifnot(identical(y1, y0))\n\nmessage(\"*** future_mapply() - special cases ...\")\n\nX <- list()\nnames(X) <- character(0L)\n\ny <- future_mapply(FUN = identity, X)\nstopifnot(length(y) == 0L, !is.null(names(y)), identical(y, X))\n\ny <- future_mapply(FUN = identity, X, X)\nstopifnot(length(y) == 0L, !is.null(names(y)), identical(y, X))\n\nmessage(\"*** future_mapply() - special cases ... DONE\")\n\nmessage(\"*** future_mapply() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_replicate.R",
    "content": "library(future.apply)\n\nmessage(\"*** future_replicate() ...\")\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n  \n  y0 <- replicate(5L, sample(10L, size = 1L))\n  y1 <- future_replicate(5L, sample(10L, size = 1L))\n  stopifnot(length(y0) == length(y1))\n  \n  set.seed(0xBEEF)\n  y1 <- future_replicate(5L, sample(10L, size = 1L))\n  set.seed(0xBEEF)\n  y2 <- future_replicate(5L, sample(10L, size = 1L))\n  stopifnot(all.equal(y2, y1))\n  \n  y3 <- future_replicate(5L, sample(10L, size = 1L), future.seed = 0xBEEF)\n  y4 <- future_replicate(5L, sample(10L, size = 1L), future.seed = 0xBEEF)\n  stopifnot(all.equal(y4, y3))\n  \n  \n  message(\"- example(replicate) ...\")\n  \n  foo <- function(x = 1, y = 2) c(x, y)\n  bar0 <- function(n, x) replicate(n, foo(x = x))\n  y0 <- bar0(5, x = 3)\n  \n  bar1 <- function(n, x) future_replicate(n, foo(x = x))\n  y1 <- bar1(5, x = 3)\n  stopifnot(all.equal(y1, y0))\n  \n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\nmessage(\"*** future_replicate() ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-future_sapply.R",
    "content": "#' @tags future_sapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_sapply() ...\")\n\nxs <- list(\n  A = c(a = 1, b = 2, c = 3),\n  B = c(a = 1:2, b = 2:3, c = 3:4),\n  C = letters[1:3],\n  D = structure(10 * 5:8, names = LETTERS[1:4])\n)\n\nFUNS <- list(\n  a = identity,\n  b = as.matrix,\n  c = function(x, y = 2 * 1:5) outer(rep(x, length.out = 3L), y)\n)\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n  \n  for (x in xs) {\n    FUNS_x <- FUNS\n    if (!is.numeric(x)) FUNS_x[[\"c\"]] <- NULL\n    \n    for (USE.NAMES in list(FALSE, TRUE)) {\n      for (simplify in list(FALSE, TRUE, \"array\")) {\n        for (FUN in FUNS_x) {\n          y0 <-        sapply(x, FUN = FUN,\n                              USE.NAMES = USE.NAMES, simplify = simplify)\n          y1 <- future_sapply(x, FUN = FUN,\n                              USE.NAMES = USE.NAMES, simplify = simplify)\n          str(list(y0 = y0, y1 = y1))\n          stopifnot(identical(y1, y0))\n          if (identical(simplify, FALSE)) {\n             y2 <- lapply(x, FUN = FUN)\n             str(list(y0 = y0, y2 = y2))\n             stopifnot(identical(unname(y2), unname(y0)))\n          }\n        }\n      }\n    }\n  }\n\n  y0 <- sapply(1:3, FUN = \"sqrt\")\n  y1 <- future_sapply(1:3, FUN = \"sqrt\")\n  stopifnot(identical(y1, y0))\n  \n  ## https://github.com/futureverse/future.apply/issues/61\n#  compute <- function(a, x_vec) a + x_vec\n#  call_compute <- function(..., x_vec = 1:2){\n#    compute_with_dots <- function(x) compute(..., x_vec = x)\n#    future_sapply(x_vec, FUN = compute_with_dots)\n#  }\n#  y <- call_compute(0L)\n#  print(y)\n#  stopifnot(identical(y, 1:2))\n  \n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\nmessage(\"*** future_sapply() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_tapply.R",
    "content": "#' @tags future_tapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nlibrary(\"datasets\") ## warpbreaks, iris\n\noptions(future.debug = FALSE)\nmessage(\"*** future_tapply() ...\")\n\nfor (strategy in supportedStrategies()[1]) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n\n  message(\"- From example(tapply) ...\")\n\n  message(\"  - Example #1\")\n  library(\"stats\")  ## rbinom()\n  groups <- as.factor(stats::rbinom(32, n = 5, prob = 0.4))\n  t <- table(groups)\n  print(t)\n  y0 <- tapply(groups, INDEX = groups, FUN = length)\n  print(y0)\n  y1 <- future_tapply(groups, INDEX = groups, FUN = length)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  y2 <- future_tapply(groups, INDEX = groups, FUN = \"length\")\n  print(y2)\n  stopifnot(all.equal(y2, y0))\n\n  message(\"  - Example #2\")\n  ## contingency table from data.frame : array with named dimnames\n  y0 <- tapply(warpbreaks$breaks, INDEX = warpbreaks[,-1], FUN = sum)\n  print(y0)\n  y1 <- future_tapply(warpbreaks$breaks, INDEX = warpbreaks[,-1], FUN = sum)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n\n  message(\"  - Example #3\")\n  y0 <- tapply(warpbreaks$breaks, warpbreaks[, 3, drop = FALSE], sum)\n  print(y0)\n  y1 <- future_tapply(warpbreaks$breaks, warpbreaks[, 3, drop = FALSE], sum)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #4\")\n  n <- 17\n  fac <- factor(rep_len(1:3, n), levels = 1:5)\n  t <- table(fac)  \n  y0 <- tapply(1:n, fac, sum)\n  print(y0)\n  y1 <- future_tapply(1:n, fac, sum)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #5\")\n  if (\"default\" %in% names(formals(tapply))) {\n    y0 <- tapply(1:n, fac, sum, default = 0) # maybe more desirable\n    print(y0)\n    y1 <- future_tapply(1:n, fac, sum, default = 0) # maybe more desirable\n    print(y1)\n    stopifnot(all.equal(y1, y0))\n  }\n  \n  message(\"  - Example #6\")\n  y0 <- tapply(1:n, fac, sum, simplify = FALSE)\n  print(y0)\n  y1 <- future_tapply(1:n, fac, sum, simplify = FALSE)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #7\")\n  y0 <- tapply(1:n, fac, range)\n  print(y0)\n  y1 <- future_tapply(1:n, fac, range)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #8\")\n  y0 <- tapply(1:n, fac, quantile)\n  print(y0)\n  y1 <- future_tapply(1:n, fac, quantile)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #9\")\n  y0 <- tapply(1:n, fac, length) ## NA's\n  print(y0)\n  y1 <- future_tapply(1:n, fac, length) ## NA's\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #10\")\n  if (\"default\" %in% names(formals(tapply))) {\n    y0 <- tapply(1:n, fac, length, default = 0) # == table(fac)\n    print(y0)\n    y1 <- future_tapply(1:n, fac, length, default = 0) # == table(fac)\n    print(y1)\n    stopifnot(all.equal(y1, y0))\n  }\n  \n  message(\"  - Example #11\")\n  ## example of ... argument: find quarterly means\n  y0 <- tapply(presidents, cycle(presidents), mean, na.rm = TRUE)\n  print(y0)\n  y1 <- future_tapply(presidents, cycle(presidents), mean, na.rm = TRUE)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #12\")\n  ind <- list(c(1, 2, 2), c(\"A\", \"A\", \"B\"))\n  t <- table(ind)\n  print(t)\n  y0 <- tapply(1:3, ind) #-> the split vector\n  print(y0)\n  y1 <- future_tapply(1:3, ind) #-> the split vector\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"  - Example #13\")\n  y0 <- tapply(1:3, ind, sum)\n  print(y0)\n  y1 <- future_tapply(1:3, ind, sum)\n  print(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  ## Some assertions (not held by all patch propsals):\n  message(\"  - Example #14\")\n  nq <- names(quantile(1:5))\n  y_truth <- c(1L, 2L, 4L)\n  stopifnot(identical(tapply(1:3, ind), y_truth))\n  stopifnot(identical(future_tapply(1:3, ind), y_truth))\n  \n  message(\"  - Example #15\")\n  y_truth <- matrix(c(1L, 2L, NA, 3L), nrow = 2L,\n                    dimnames = list(c(\"1\", \"2\"), c(\"A\", \"B\")))\n  stopifnot(identical(tapply(1:3, ind, sum), y_truth))\n  stopifnot(identical(future_tapply(1:3, ind, sum), y_truth))\n  \n  message(\"  - Example #16\")\n  y_truth <- array(list(\n    `2` = structure(c(2, 5.75, 9.5, 13.25, 17), .Names = nq),\n    `3` = structure(c(3, 6, 9, 12, 15), .Names = nq),\n    `4` = NULL, `5` = NULL),\n    dim = 4L, dimnames = list(as.character(2:5)))\n  stopifnot(identical(tapply(1:n, fac, quantile)[-1], y_truth))\n  stopifnot(identical(future_tapply(1:n, fac, quantile)[-1], y_truth))\n\n  if (getRversion() >= \"4.3.0\") {\n    data <- iris[, c(\"Sepal.Length\", \"Sepal.Width\")]\n    y_truth <- tapply(data, INDEX = iris$Species, FUN = sum)\n    y <- future_tapply(data, INDEX = iris$Species, FUN = sum)\n    stopifnot(identical(y, y_truth))\n    \n    y_truth2 <- tapply(data, INDEX = ~ iris$Species + iris$Petal.Width, FUN = sum)\n    y2 <- future_tapply(data, INDEX = ~ iris$Species + iris$Petal.Width, FUN = sum)\n    stopifnot(identical(y2, y_truth2))\n  }\n\n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\n\nmessage(\"*** exceptions ...\")\n\n## Error: 'INDEX' is of length zero\nres <- tryCatch({\n  y <- future_tapply(1L, INDEX = list())\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n## Error: total number of levels >= 2^31\nres <- tryCatch({\n  y <- future_tapply(1:216, INDEX = rep(list(1:216), times = 4L))\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\n## Error: arguments must have same length\nres <- tryCatch({\n  y <- future_tapply(1L, INDEX = list(1:2))\n}, error = identity)\nstopifnot(inherits(res, \"error\"))\n\nmessage(\"*** future_tapply() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-future_vapply.R",
    "content": "#' @tags future_vapply\n#' @tags detritus-files\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_vapply() ...\")\n\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  plan(strategy)\n  \n  x <- NULL\n  fun <- is.factor\n  fun_name <- \"is.factor\"\n  fun_value <- logical(1L)\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  y2 <- future_vapply(x, FUN = fun_name, FUN.VALUE = fun_value)\n  str(y2)\n  stopifnot(all.equal(y2, y0))\n  \n  x <- list()\n  fun <- is.numeric\n  fun_value <- logical(1L)\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  x <- integer()\n  fun <- identity\n  fun_value <- fun(integer(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  \n  df <- data.frame(x = 1:10, y = letters[1:10], stringsAsFactors=FALSE)\n  fun <- class\n  fun_value <- character(1L)\n  y0 <- vapply(df, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(df, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  x <- 1:10\n  fun <- function(x) double(0L)\n  fun_value <- fun(double(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  fun <- function(x) integer(0L)\n  fun_value <- fun(double(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  fun <- sqrt\n  fun_value <- fun(double(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  fun <- function(x) c(x, x^2)\n  fun_value <- fun(double(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  fun <- function(x) matrix(x, nrow = 2L, ncol = 2L)\n  fun_value <- fun(integer(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  fun <- function(x) matrix(x, nrow = 2L, ncol = 2L)\n  fun_value <- fun(double(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n\n  ## Ditto with dimnames on FUN.VALUE\n  fun <- function(x) {\n    matrix(x, nrow = 2L, ncol = 2L, dimnames = list(c(\"a\", \"b\"), c(\"A\", \"B\")))\n  }\n  fun_value <- fun(double(1L))\n  y0 <- vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y0)\n  y1 <- future_vapply(x, FUN = fun, FUN.VALUE = fun_value)\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  message(\"- From example(vapply) ...\")\n  x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE, FALSE, FALSE, TRUE))\n  y0 <- vapply(x, FUN = quantile, FUN.VALUE = double(5L))\n  y1 <- future_vapply(x, FUN = quantile, FUN.VALUE = double(5L))\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n  \n  i39 <- sapply(3:9, seq)\n  ys0 <- sapply(i39, fivenum)\n  ys1 <- future_sapply(i39, fivenum)\n  stopifnot(all.equal(ys1, ys0))\n  \n  yv0 <- vapply(i39, fivenum,\n          c(Min. = 0, \"1st Qu.\" = 0, Median = 0, \"3rd Qu.\" = 0, Max. = 0))\n  yv1 <- future_vapply(i39, fivenum,\n         c(Min. = 0, \"1st Qu.\" = 0, Median = 0, \"3rd Qu.\" = 0, Max. = 0))\n  str(yv1)\n  stopifnot(all.equal(yv1, yv0))\n  \n  v <- structure(10*(5:8), names = LETTERS[1:4])\n  f <- function(x, y) outer(rep(x, length.out = 3L), y)\n  ys0 <- sapply(v, f, y = 2*(1:5), simplify = \"array\")\n  ys1 <- future_sapply(v, f, y = 2*(1:5), simplify = \"array\")\n  stopifnot(all.equal(ys1, ys0))\n  \n  fv <- outer(1:3, 1:5)\n  y <- 2*(1:5)\n  yv0 <- vapply(v, f, fv, y = y)\n  yv1 <- future_vapply(v, f, fv, y = y)\n  str(yv1)\n  stopifnot(all.equal(yv1, yv0))\n  \n  y0 <- vapply(mtcars, FUN = is.numeric, FUN.VALUE = logical(1L))\n  y1 <- future_vapply(mtcars, FUN = is.numeric, FUN.VALUE = logical(1L))\n  str(y1)\n  stopifnot(all.equal(y1, y0))\n\n  message(\"- future_vapply(x, ...) where length(x) != length(as.list(x)) ...\")\n  x <- structure(list(a = 1, b = 2), class = \"Foo\")\n  as.list.Foo <- function(x, ...) c(x, c = 3)\n  y0 <- vapply(x, FUN = length, FUN.VALUE = -1L)\n  y1 <- future_vapply(x, FUN = length, FUN.VALUE = -1L)\n  stopifnot(identical(y1, y0))\n\n  message(\"- exceptions ...\")\n  res <- tryCatch({\n    y0 <- vapply(1:3, FUN = identity, FUN.VALUE = c(3, 3))\n  }, error = identity)\n  stopifnot(inherits(res, \"error\"))\n  res <- tryCatch({\n    y1 <- future_vapply(1:3, FUN = identity, FUN.VALUE = c(3, 3))\n  }, error = identity)\n  stopifnot(inherits(res, \"error\"))\n  \n  plan(sequential)\n  message(sprintf(\"*** strategy = %s ... done\", sQuote(strategy)))\n} ## for (strategy in ...) \n\n\nmessage(\"*** future_vapply() ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-globals,tricky2.R",
    "content": "#' @tags future_apply\n#' @tags globals\n#' @tags detritus-files\n#' @tags sequential multisession multicore\n\nif (packageVersion(\"future\") > \"1.49.0\" && isTRUE(getOption(\"future.globals.keepWhere\"))) {\n\n  library(future.apply)\n  options(future.debug = FALSE)\n  \n  foo <- function(..., FUN = function(...) list(...)) {\n    args <- list(...)\n    future_lapply(1L, FUN = function(x) {\n      do.call(FUN, args = c(list(x), args))\n    })\n  }\n  \n  bar <- function(..., fun = function(...) list(...)) {\n    future_lapply(1L, FUN = function(x) fun(x, ...))\n  }\n  \n  yaa <- function(..., FUN = function(...) list(...)) {\n    future_lapply(1L, FUN = function(x) {\n      do.call(FUN, args = c(list(x), ...))\n    })\n  }\n  \n  for (strategy in supportedStrategies()) {\n    message(sprintf(\"- plan('%s') ...\", strategy))\n    plan(strategy)\n  \n    x1 <- foo()\n    y1 <- bar()\n    stopifnot(identical(y1, x1))\n    z1 <- yaa()\n    stopifnot(identical(z1, x1))\n  \n    x2 <- foo(a = 2)\n    y2 <- bar(a = 2)\n    z2 <- yaa(a = 2)\n    stopifnot(identical(y2, x2))\n    stopifnot(identical(z2, x2))\n    \n    message(sprintf(\"- plan('%s') ... done\", strategy))\n  }\n\n} ## if (packageVersion(\"future\") > ...)\n"
  },
  {
    "path": "inst/testme/test-globals,tricky_recursive.R",
    "content": "#' @tags future_apply\n#' @tags globals\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\n## Test adopted from http://stackoverflow.com/questions/42561088/nested-do-call-within-a-foreach-dopar-environment-cant-find-function-passed-w\n\noptions(future.debug = FALSE)\n\nmessage(\"*** Tricky globals requiring recursive search ...\")\n\nmy_add <- function(a, b) a + b\n\ncall_my_add <- function(a, b) {\n  do.call(my_add, args = list(a = a, b = b))\n}\n\ncall_my_add_caller <- function(a, b, FUN = call_my_add) {\n  do.call(FUN, args = list(a = a, b = b))\n}\n\nmain_lapply <- function(x = 1:2, caller = call_my_add_caller,\n                               args = list(FUN = call_my_add)) {\n  lapply(x, FUN = function(i) {\n    do.call(caller, args = c(list(a = i, b = i+1L), args))\n  })\n}\n\nmain_lapply_no_FUN <- function(x = 1:2, caller = call_my_add_caller,\n                               args = list(FUN = call_my_add)) {\n  lapply(x, FUN = function(i) {\n    do.call(caller, args = list(a = i, b = i+1L))\n  })\n}\n\nmain_future_lapply <- function(x = 1:2, caller = call_my_add_caller,\n                               args = list(FUN = call_my_add)) {\n  future_lapply(x, FUN = function(i) {\n    do.call(caller, args = c(list(a = i, b = i + 1L), args))\n  })\n}\n\nmain_future_lapply_no_FUN <- function(x = 1:2, caller = call_my_add_caller,\n                               args = list(FUN = call_my_add)) {\n  future_lapply(x, FUN = function(i) {\n    do.call(caller, args = list(a = i, b = i + 1L))\n  })\n}\n\nx0 <- y0 <- z0 <- NULL\nfor (strategy in supportedStrategies()) {\n  message(sprintf(\"*** strategy = %s ...\", sQuote(strategy)))\n  \n  plan(strategy)\n\n  z <- main_lapply()\n  str(list(z = z))\n  if (is.null(z0)) z0 <- z\n  stopifnot(identical(z, z0))\n\n  z2 <- main_lapply_no_FUN()\n  str(list(z2 = z2))\n  stopifnot(identical(z2, z0))\n  \n  z3 <- main_future_lapply()\n  str(list(z3 = z3))\n  stopifnot(identical(z3, z0))\n\n  z4 <- main_future_lapply_no_FUN()\n  str(list(z4 = z4))\n  stopifnot(identical(z4, z0))\n  \n  message(sprintf(\"*** strategy = %s ... DONE\", sQuote(strategy)))\n}\n\nmessage(\"*** Tricky globals requiring recursive search ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-options,nested.R",
    "content": "#' @tags future_lapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** Options in nested parallelization ...\")\n\noptions(future.debug = FALSE)\noptions(future.apply.debug = FALSE)\noptions(future.globals.maxSize = 2.50 * 1024^2)\n\nfor (cores in 1:availCores) {\n  message(sprintf(\"Testing with %d cores ...\", cores))\n  options(mc.cores = cores)\n  strategies <- supportedStrategies(cores)\n\n  for (strategy1 in strategies) {\n    for (strategy2 in strategies) {\n      message(sprintf(\"- plan(list('%s', '%s')) ...\", strategy1, strategy2))\n      plan(list(outer = strategy1, inner = strategy2))\n\n      v <- future_lapply(1:2, FUN = function(x) {\n        outer <- data.frame(\n          label   = \"outer\",\n          idx     = x,\n          pid     = Sys.getpid(),\n          maxSize = getOption(\"future.globals.maxSize\", NA_real_)\n        )\n        \n        inner <- future_lapply(3:4, FUN = function(x) {\n          data.frame(\n            label   = \"inner\",\n            idx     = x,\n            pid     = Sys.getpid(),\n            maxSize = getOption(\"future.globals.maxSize\", NA_real_))\n        })\n        inner <- do.call(rbind, inner)\n        rbind(outer, inner)\n      })\n      v <- do.call(rbind, v)\n      print(v)\n      stopifnot(!anyNA(v$maxSize))\n    } ## for (strategy2 ...)\n  } ## for (strategy1 ...)\n} ## for (cores in ...)\n\nmessage(\"*** Options in nested parallelization ... done\")\n"
  },
  {
    "path": "inst/testme/test-rng.R",
    "content": "#' @tags rng\n\nloadNamespace(\"future.apply\")\n\nmessage(\"*** RNG ...\")\n\nset_random_seed(seed = NULL)\nseed <- get_random_seed()\nstopifnot(is.null(seed))\n\nset_random_seed(seed = 42L)\nseed <- get_random_seed()\nstopifnot(identical(seed, 42L))\n\nres <- tryCatch({\n  seed <- as_lecyer_cmrg_seed(seed = FALSE)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\nseed <- as_lecyer_cmrg_seed(seed = 42L)\nstr(seed)\nstopifnot(is_lecyer_cmrg_seed(seed))\nset_random_seed(seed = seed)\nstopifnot(identical(get_random_seed(), seed))\n\nseed2 <- as_lecyer_cmrg_seed(seed = TRUE)\nstr(seed2)\nstopifnot(identical(seed2, seed))\n\nseed3 <- as_lecyer_cmrg_seed(seed = seed)\nstr(seed3)\nstopifnot(identical(seed3, seed))\n\n## A random seed\nseed4 <- as_lecyer_cmrg_seed(seed = NA)\nstr(seed4)\nstopifnot(is_lecyer_cmrg_seed(seed4))\n\n\nmessage(\" - make_rng_seeds ...\")\n\nseeds <- make_rng_seeds(2L, seed = NULL)\nstopifnot(is.null(seeds))\n\nseeds <- make_rng_seeds(2L, seed = FALSE)\nstopifnot(is.null(seeds))\n\nseeds <- make_rng_seeds(0L, seed = 42L)\nstopifnot(length(seeds) == 0L, identical(seeds, list()))\n\nseeds <- make_rng_seeds(2L, seed = TRUE)\nstopifnot(length(seeds) == 2L, all(sapply(seeds, FUN = is_lecyer_cmrg_seed)))\n\nseeds <- make_rng_seeds(3L, seed = 42L)\nstopifnot(length(seeds) == 3L, all(sapply(seeds, FUN = is_lecyer_cmrg_seed)))\n\nseeds <- make_rng_seeds(1L, seed = 42L)\nstopifnot(length(seeds) == 1L, all(sapply(seeds, FUN = is_lecyer_cmrg_seed)))\n\nseeds0 <- lapply(1:3, FUN = as_lecyer_cmrg_seed)\nseeds <- make_rng_seeds(length(seeds0), seed = seeds0)\nstopifnot(length(seeds) == length(seeds0),\n          all(sapply(seeds, FUN = is_lecyer_cmrg_seed)))\n\n\nmessage(\" - exceptions ...\")\n\n## Invalid L'Ecuyer seed\nseed_invalid <- seed + 1L\nres <- tryCatch({\n  seed <- as_lecyer_cmrg_seed(seed = seed_invalid)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n## Invalid seed\nres <- tryCatch({\n  seed <- as_lecyer_cmrg_seed(seed = 1:2)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n## Invalid length\nseeds0 <- lapply(1:2, FUN = as_lecyer_cmrg_seed)\nres <- tryCatch({\n  seeds <- make_rng_seeds(1L, seed = seeds0)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n## Seeds of different kinds\nseeds0 <- lapply(1:2, FUN = as_lecyer_cmrg_seed)\nseeds0[[1]] <- seeds0[[1]][-1]\nres <- tryCatch({\n  seeds <- make_rng_seeds(2L, seed = seeds0)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n## List of scalar seeds?\nres <- tryCatch({\n  seeds <- make_rng_seeds(1L, seed = list(42L))\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n## Not seeds at all?\nseeds0 <- lapply(1:2, FUN = as_lecyer_cmrg_seed)\nseeds0[[1]] <- letters[1:7]\nres <- tryCatch({\n  seeds <- make_rng_seeds(2L, seed = seeds0)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n## Invalid seeds?\nseeds0 <- lapply(1:2, FUN = as_lecyer_cmrg_seed)\nseeds0 <- lapply(seeds0, FUN = rev)\nres <- tryCatch({\n  seeds <- make_rng_seeds(2L, seed = seeds0)\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"error\"))\n\n\nmessage(\" - replicated RNG draws\")\nlibrary(future.apply)\n\nseed_org <- next_random_seed()\nset.seed(42)\n\n## Draw two random number from 1:100 one after the other\nseed_before <- get_random_seed()\nkind_before <- RNGkind()\nx <- sample.int(100L, size = 5L)\ny <- sample.int(100L, size = 5L)\nseed_after <- get_random_seed()\nkind_after <- RNGkind()\nprint(c(x, y))\n\n## Draw two random number from 1:100 at once\nset_random_seed(seed_before)\nkind_before2 <- RNGkind()\nz <- sample.int(100L, size = 10L)\nseed_after2 <- get_random_seed()\nkind_after2 <- RNGkind()\nprint(z)\n\n## The RNG state is the same after the second ...\n## run as after the first, two-step, approach\nstopifnot(identical(seed_after2, seed_after))\nstopifnot(identical(kind_before2, kind_before))\nstopifnot(identical(kind_after2, kind_after))\n\n## .... and the exact same set of random numbers where\n## drawn [only true in R (>= 4.0.0)]\nif (getRversion() >= \"4.0.0\") {\n  stopifnot(identical(z, c(x, y)))\n} else {\n  stopifnot(identical(z[seq_along(x)], x))\n}\n\nset_random_seed(seed_org)\nstopifnot(identical(get_random_seed(), seed_org))\n\nmessage(\"*** RNG ... DONE\")\n"
  },
  {
    "path": "inst/testme/test-stdout.R",
    "content": "#' @tags future_lapply future_mapply\n#' @tags sequential multisession multicore\n\nlibrary(future.apply)\n\nmessage(\"*** future_*apply() and 'future.stdout' ...\")\n\noptions(future.debug = TRUE)\n\ntruth <- list()\n\nout <- utils::capture.output({\n  y <- lapply(1:0, FUN = function(x) {\n    print(x)\n  })\n})\ntruth[[\"lapply\"]] <- list(value = y, stdout = out)\n\nout <- utils::capture.output({\n  y <- mapply(1:0, 0:1, FUN = function(x, y) {\n    print(list(x = x, y = y))\n  })\n})\ntruth[[\"mapply\"]] <- list(value = y, stdout = out)\n\nfor (cores in 1:availCores) {\n  message(sprintf(\"  - Testing with %d cores ...\", cores))\n  options(mc.cores = cores)\n  \n  for (strategy in supportedStrategies(cores)) {\n    message(sprintf(\"* plan('%s') ...\", strategy))\n    plan(strategy)\n\n    for (fun in names(truth)) {\n      for (stdout in c(FALSE, TRUE, NA)) {\n        message(sprintf(\"* future_%s(x, ..., future.stdout = %s) ...\", fun, stdout))\n  \n        out <- utils::capture.output({\n          if (fun == \"lapply\") {\n            y <- future_lapply(1:0, FUN = function(x) {\n              Sys.sleep(x / 2)  ## make futures resolve out of order\n\t      print(x)\n            }, future.stdout = stdout)\n\t  } else if (fun == \"mapply\") {\n            y <- future_mapply(1:0, 0:1, FUN = function(x, y) {\n              Sys.sleep(x / 2)  ## make futures resolve out of order\n              print(list(x = x, y = y))\n            }, future.stdout = stdout)\n\t  }\n        })\n        stopifnot(identical(y, truth[[fun]]$value))\n  \n        if (isTRUE(stdout)) {\n          stopifnot(identical(out, truth[[fun]]$stdout))\n        } else if (is.na(stdout)) {\n        } else {\n          stopifnot(nchar(out) == 0)\n        }\n      \n        message(sprintf(\"* future_%s(x, ..., future.stdout = %s) ... DONE\", fun, stdout))\n      } ## for (stdout ...)\n    } ## for (fun ...)\n    \n    message(sprintf(\"* plan('%s') ... DONE\", strategy))\n  }\n  \n  message(sprintf(\"  - Testing with %d cores ... DONE\", cores))\n}\n\nmessage(\"*** future_*apply() and 'future.stdout' ... DONE\")\n\n\n"
  },
  {
    "path": "inst/testme/test-utils.R",
    "content": "loadNamespace(\"future.apply\")\nstop_if_not <- future.apply:::stop_if_not\n\nmessage(\"*** utils ...\")\n\nmessage(\"*** hpaste() ...\")\n\n# Some vectors\nx <- 1:6\ny <- 10:1\nz <- LETTERS[x]\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n# Abbreviation of output vector\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nprintf(\"x = %s.\\n\", hpaste(x))\n## x = 1, 2, 3, ..., 6.\n\nprintf(\"x = %s.\\n\", hpaste(x, maxHead = 2))\n## x = 1, 2, ..., 6.\n\nprintf(\"x = %s.\\n\", hpaste(x, maxHead = 3)) # Default\n## x = 1, 2, 3, ..., 6.\n\n# It will never output 1, 2, 3, 4, ..., 6\nprintf(\"x = %s.\\n\", hpaste(x, maxHead = 4))\n## x = 1, 2, 3, 4, 5 and 6.\n\n# Showing the tail\nprintf(\"x = %s.\\n\", hpaste(x, maxHead = 1, maxTail = 2))\n## x = 1, ..., 5, 6.\n\n# Turning off abbreviation\nprintf(\"y = %s.\\n\", hpaste(y, maxHead = Inf))\n## y = 10, 9, 8, 7, 6, 5, 4, 3, 2, 1\n\n## ...or simply\nprintf(\"y = %s.\\n\", paste(y, collapse = \", \"))\n## y = 10, 9, 8, 7, 6, 5, 4, 3, 2, 1\n\n# Change last separator\nprintf(\"x = %s.\\n\", hpaste(x, lastCollapse = \" and \"))\n## x = 1, 2, 3, 4, 5 and 6.\n\n# No collapse\nstopifnot(all(hpaste(x, collapse = NULL) == x))\n\n# Empty input\nstopifnot(identical(hpaste(character(0)), character(0)))\n\nmessage(\"*** hpaste() ...\")\n\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n# debug()\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nmessage(\"*** mdebug() ...\")\n\nmdebug(\"Hello #\", 1)\nmdebugf(\"Hello #%d\", 1)\noptions(future.debug = TRUE)\n\nmdebug(\"Hello #\", 2)\nmdebugf(\"Hello #%d\", 2)\noptions(future.debug = FALSE)\n\nmdebug(\"Hello #\", 3)\nmdebugf(\"Hello #%d\", 3)\n\nmessage(\"*** mdebug() ... DONE\")\n\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n# import_from()\n# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nmessage(\"*** import_from() ...\")\n\nobj <- import_from(\"non-existing-fcn\", default = NA, package = \"future\")\nstopifnot(identical(obj, NA))\n\nres <- tryCatch({\n  obj <- import_from(\"non-existing-fcn\", package = \"future\")\n}, error = identity)\nprint(res)\nstopifnot(inherits(res, \"simpleError\"))\n\nmessage(\"*** import_from() ... DONE\")\n\n\nmessage(\"*** stop_if_not() ...\")\n\nstop_if_not(TRUE)\nstop_if_not(TRUE, TRUE)\nres <- tryCatch({\n  stop_if_not(FALSE)\n}, error = identity)\nstopifnot(inherits(res, \"simpleError\"))\nres <- tryCatch({\n  stop_if_not(list(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE))\n}, error = identity)\nstopifnot(inherits(res, \"simpleError\"))\n\nmessage(\"*** stop_if_not() ... DONE\")\n\n\nmessage(\"*** assert_values2() ...\")\n\nassert_values2 <- future.apply:::assert_values2\nassert_values2(nX = 2L, values2 = as.list(1:2))\nres <- tryCatch({\n  assert_values2(nX = 1L, values = as.list(1:2), values2 = as.list(1:2), fcn = \"tests\", debug = TRUE)\n}, error = identity)\nstopifnot(inherits(res, \"FutureError\"))\n\nmessage(\"*** assert_values2() ... DONE\")\n\n\nmessage(\"*** utils ... DONE\")\n\n\n"
  },
  {
    "path": "man/fold.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/fold.R\n\\name{fold}\n\\alias{fold}\n\\title{Efficient Fold, Reduce, Accumulate, Combine of a Vector}\n\\usage{\nfold(x, f, left = TRUE, unname = TRUE, threshold = 1000L)\n}\n\\arguments{\n\\item{x}{A vector.}\n\n\\item{f}{A binary function, i.e. a function take takes two arguments.}\n\n\\item{left}{If \\code{TRUE}, vector is combined from the left (the first element),\notherwise the right (the last element).}\n\n\\item{unname}{If \\code{TRUE}, function \\code{f} is called as\n\\code{f(unname(y), x[[ii]])}, otherwise as \\code{f(y, x[[ii]])},\nwhich may introduce name \\code{\"y\"}.}\n\n\\item{threshold}{An integer (>= 2) specifying the length where the\nrecursive divide-and-conquer call will stop and incremental building of\nthe partial value is performed.  Using \\code{threshold = +Inf} will disable\nrecursive folding.}\n}\n\\value{\nA vector.\n}\n\\description{\nEfficient Fold, Reduce, Accumulate, Combine of a Vector\n}\n\\details{\nIn order for recursive folding to give the same results as non-recursive\nfolding, binary function \\code{f} must be \\emph{associative} with itself, i.e.\n\\code{f(f(x[[1]], x[[2]]), x[[3]])} equals\n\\code{f(x[[1]], f(x[[2]]), x[[3]])}.\n\nThis function is a more efficient (memory and speed) of\n\\code{\\link[base:Reduce]{Reduce(f, x, right = !left, accumulate = FALSE)}},\nespecially when \\code{x} is long.\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/future.apply.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/future.apply-package.R\n\\docType{package}\n\\name{future.apply}\n\\alias{future.apply}\n\\alias{future.apply-package}\n\\title{future.apply: Apply Function to Elements in Parallel using Futures}\n\\description{\nThe \\pkg{future.apply} package provides parallel implementations of\ncommon \"apply\" functions provided by base \\R.  The parallel processing\nis performed via the \\pkg{future} ecosystem, which provides a large\nnumber of parallel backends, e.g. on the local machine, a remote cluster,\nand a high-performance compute cluster.\n}\n\\details{\nCurrently implemented functions are:\n\\itemize{\n\\item \\code{\\link[=future_apply]{future_apply()}}: a parallel version of \\link[base:apply]{apply()}\n\\item \\code{\\link[=future_by]{future_by()}}: a parallel version of \\link[base:by]{by()}\n\\item \\code{\\link[=future_eapply]{future_eapply()}}: a parallel version of \\link[base:lapply]{eapply()}\n\\item \\code{\\link[=future_lapply]{future_lapply()}}: a parallel version of \\link[base:lapply]{lapply()}\n\\item \\code{\\link[=future_mapply]{future_mapply()}}: a parallel version of \\link[base:mapply]{mapply()}\n\\item \\code{\\link[=future_sapply]{future_sapply()}}: a parallel version of \\link[base:lapply]{sapply()}\n\\item \\code{\\link[=future_tapply]{future_tapply()}}: a parallel version of \\link[base:tapply]{tapply()}\n\\item \\code{\\link[=future_vapply]{future_vapply()}}: a parallel version of \\link[base:lapply]{vapply()}\n\\item \\code{\\link[=future_Map]{future_Map()}}: a parallel version of \\link[=Map]{Map()}\n\\item \\code{\\link[=future_replicate]{future_replicate()}}: a parallel version of \\link[base:lapply]{replicate()}\n\\item \\code{\\link[=future_.mapply]{future_.mapply()}}: a parallel version of \\link[base:mapply]{.mapply()}\n}\n\nReproducibility is part of the core design, which means that perfect,\nparallel random number generation (RNG) is supported regardless of the\namount of chunking, type of load balancing, and future backend being used.\n\nSince these \\verb{future_*()} functions have the same arguments as the\ncorresponding base \\R function, start using them is often as simple as\nrenaming the function in the code.  For example, after attaching the package:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{library(future.apply)\n}\\if{html}{\\out{</div>}}\n\ncode such as:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE))\ny <- lapply(x, quantile, probs = 1:3/4)\n}\\if{html}{\\out{</div>}}\n\ncan be updated to:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{y <- future_lapply(x, quantile, probs = 1:3/4)\n}\\if{html}{\\out{</div>}}\n\nThe default settings in the \\pkg{future} framework is to process code\n\\emph{sequentially}.  To run the above in parallel on the local machine\n(on any operating system), use:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{plan(multisession)\n}\\if{html}{\\out{</div>}}\n\nfirst.  That's it!\n\nTo go back to sequential processing, use \\code{plan(sequential)}.\nIf you have access to multiple machines on your local network, use:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{plan(cluster, workers = c(\"n1\", \"n2\", \"n2\", \"n3\"))\n}\\if{html}{\\out{</div>}}\n\nThis will set up four workers, one on \\code{n1} and \\code{n3}, and two on \\code{n2}.\nIf you have SSH access to some remote machines, use:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{plan(cluster, workers = c(\"m1.myserver.org\", \"m2.myserver.org))\n}\\if{html}{\\out{</div>}}\n\nSee the \\pkg{future} package and \\code{\\link[future:plan]{future::plan()}} for more examples.\n\nThe \\pkg{future.batchtools} package provides support for high-performance\ncompute (HPC) cluster schedulers such as SGE, Slurm, and TORQUE / PBS.\nFor example,\n\\itemize{\n\\item \\code{plan(batchtools_slurm)}:\nProcess via a Slurm scheduler job queue.\n\\item \\code{plan(batchtools_torque)}:\nProcess via a TORQUE / PBS scheduler job queue.\n}\n\nThis builds on top of the queuing framework that the \\pkg{batchtools}\npackage provides. For more details on backend configuration, please see\nthe \\pkg{future.batchtools} and \\pkg{batchtools} packages.\n\nThese are just a few examples of parallel/distributed backend for the\nfuture ecosystem.  For more alternatives, see the 'Reverse dependencies'\nsection on the\n\\href{https://cran.r-project.org/package=future}{future CRAN package page}.\n}\n\\seealso{\nUseful links:\n\\itemize{\n  \\item \\url{https://future.apply.futureverse.org}\n  \\item \\url{https://github.com/futureverse/future.apply}\n  \\item Report bugs at \\url{https://github.com/futureverse/future.apply/issues}\n}\n\n}\n\\author{\nHenrik Bengtsson, except for the implementations of \\code{future_apply()},\n\\code{future_Map()}, \\code{future_replicate()}, \\code{future_sapply()}, and\n\\code{future_tapply()}, which are adopted from the source code of the\ncorresponding base \\R functions, which are licensed under GPL (>= 2)\nwith 'The R Core Team' as the copyright holder.\nBecause of these dependencies, the license of this package is GPL (>= 2).\n}\n\\keyword{iteration}\n\\keyword{manip}\n\\keyword{programming}\n"
  },
  {
    "path": "man/future.apply.options.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/options.R\n\\name{future.apply.options}\n\\alias{future.apply.options}\n\\alias{future.apply.debug}\n\\alias{R_FUTURE_APPLY_DEBUG}\n\\title{Options used for future.apply}\n\\description{\nBelow are the \\R options and environment variables that are used by the\n\\pkg{future.apply} package and packages enhancing it.\\cr\n\\cr\n\\emph{WARNING: Note that the names and the default values of these options may\nchange in future versions of the package.  Please use with care until\nfurther notice.}\n}\n\\details{\nFor settings specific to the \\pkg{future} package, see\n\\link[future:zzz-future.options]{future::future.options} page.\n}\n\\section{Options for debugging future.apply}{\n\n\\describe{\n\\item{\\option{future.apply.debug}:}{(logical) If \\code{TRUE}, extensive debug messages are generated. (Default: \\code{FALSE})}\n}\n}\n\n\\section{Environment variables that set R options}{\n\nAll of the above \\R \\option{future.apply.*} options can be set by\ncorresponding environment variable \\env{R_FUTURE_APPLY_*} \\emph{when the\n\\pkg{future.apply} package is loaded}.\nFor example, if \\code{R_FUTURE_APPLY_DEBUG=TRUE}, then option\n\\option{future.apply.debug} is set to \\code{TRUE} (logical).\n}\n\n\\examples{\n\\dontrun{\noptions(future.apply.debug = TRUE)\n}\n\n}\n\\seealso{\nTo set \\R options or environment variables when \\R starts (even before the \\pkg{future} package is loaded), see the \\link[base]{Startup} help page.  The \\href{https://cran.r-project.org/package=startup}{\\pkg{startup}} package provides a friendly mechanism for configuring \\R's startup process.\n}\n"
  },
  {
    "path": "man/future_apply.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/future_apply.R\n\\name{future_apply}\n\\alias{future_apply}\n\\title{Apply Functions Over Array Margins via Futures}\n\\usage{\nfuture_apply(\n  X,\n  MARGIN,\n  FUN,\n  ...,\n  simplify = TRUE,\n  future.envir = parent.frame(),\n  future.stdout = TRUE,\n  future.conditions = \"condition\",\n  future.globals = TRUE,\n  future.packages = NULL,\n  future.seed = FALSE,\n  future.scheduling = 1,\n  future.chunk.size = NULL,\n  future.label = \"future_apply-\\%d\"\n)\n}\n\\arguments{\n\\item{X}{an array, including a matrix.}\n\n\\item{MARGIN}{A vector giving the subscripts which the function will be\napplied over. For example, for a matrix \\code{1} indicates rows, \\code{2} indicates\ncolumns, \\code{c(1, 2)} indicates rows and columns.\nWhere \\code{X} has named dimnames, it can be a character vector selecting\ndimension names.}\n\n\\item{FUN}{A function taking at least one argument.}\n\n\\item{simplify}{a logical indicating whether results should be simplified\nif possible.}\n\n\\item{future.envir}{An \\link{environment} passed as argument \\code{envir} to\n\\code{\\link[future:future]{future::future()}} as-is.}\n\n\\item{future.stdout}{If \\code{TRUE} (default), then the standard output of the\nunderlying futures is captured, and re-outputted as soon as possible.\nIf \\code{FALSE}, any output is silenced (by sinking it to the null device\nas it is outputted).\nIf \\code{NA} (not recommended), output is \\emph{not} intercepted.}\n\n\\item{future.conditions}{A character string of conditions classes to be\ncaptured and relayed.  The default is the same as the \\code{condition}\nargument of \\code{\\link[future:Future-class]{future::Future()}}.\nTo not intercept conditions, use \\code{conditions = character(0L)}.\nErrors are always relayed.}\n\n\\item{future.globals}{A logical, a character vector, or a named list for\ncontrolling how globals are handled. For details, see below section.}\n\n\\item{future.packages}{(optional) a character vector specifying packages\nto be attached in the R environment evaluating the future.}\n\n\\item{future.seed}{A logical or an integer (of length one or seven),\nor a list of \\code{length(X)} with pre-generated random seeds.\nFor details, see below section.}\n\n\\item{future.scheduling}{Average number of futures (\"chunks\") per worker.\nIf \\code{0.0}, then a single future is used to process all elements\nof \\code{X}.\nIf \\code{1.0} or \\code{TRUE}, then one future per worker is used.\nIf \\code{2.0}, then each worker will process two futures\n(if there are enough elements in \\code{X}).\nIf \\code{Inf} or \\code{FALSE}, then one future per element of\n\\code{X} is used.\nOnly used if \\code{future.chunk.size} is \\code{NULL}.}\n\n\\item{future.chunk.size}{The average number of elements per future (\"chunk\").\nIf \\code{Inf}, then all elements are processed in a single future.\nIf \\code{NULL}, then argument \\code{future.scheduling} is used.}\n\n\\item{future.label}{If a character string, then each future is assigned\na label \\code{sprintf(future.label, chunk_idx)}.  If TRUE, then the\nsame as \\code{future.label = \"future_lapply-\\%d\"}.  If FALSE, no labels\nare assigned.}\n\n\\item{\\ldots}{(optional) Additional arguments passed to \\code{FUN()}, except\n\\verb{future.*} arguments, which are passed on to \\code{\\link[=future_lapply]{future_lapply()}} used\ninternally.}\n}\n\\value{\nReturns a vector or array or list of values obtained by applying a\nfunction to margins of an array or matrix.\nSee \\code{\\link[base:apply]{base::apply()}} for details.\n}\n\\description{\n\\code{future_apply()} implements \\code{\\link[base:apply]{base::apply()}} using future with perfect\nreplication of results, regardless of future backend used.\nIt returns a vector or array or list of values obtained by applying a\nfunction to margins of an array or matrix.\n}\n\\examples{\n## ---------------------------------------------------------\n## apply()\n## ---------------------------------------------------------\nX <- matrix(c(1:4, 1, 6:8), nrow = 2L)\n\nY0 <- apply(X, MARGIN = 1L, FUN = table)\nY1 <- future_apply(X, MARGIN = 1L, FUN = table)\nprint(Y1)\nstopifnot(all.equal(Y1, Y0, check.attributes = FALSE)) ## FIXME\n\nY0 <- apply(X, MARGIN = 1L, FUN = stats::quantile)\nY1 <- future_apply(X, MARGIN = 1L, FUN = stats::quantile)\nprint(Y1)\nstopifnot(all.equal(Y1, Y0))\n\n\n## ---------------------------------------------------------\n## Parallel Random Number Generation\n## ---------------------------------------------------------\n\\donttest{\n## Regardless of the future plan, the number of workers, and\n## where they are, the random numbers produced are identical\n\nX <- matrix(c(1:4, 1, 6:8), nrow = 2L)\n\nplan(multisession)\nset.seed(0xBEEF)\nY1 <- future_apply(X, MARGIN = 1L, FUN = sample, future.seed = TRUE)\nprint(Y1)\n\nplan(sequential)\nset.seed(0xBEEF)\nY2 <- future_apply(X, MARGIN = 1L, FUN = sample, future.seed = TRUE)\nprint(Y2)\n\nstopifnot(all.equal(Y1, Y2))\n}\n\n\\dontshow{\n## R CMD check: make sure any open connections are closed afterward\nif (!inherits(plan(), \"sequential\")) plan(sequential)\n}\n}\n\\author{\nThe implementation of \\code{future_apply()} is adopted from the source code\nof the corresponding base \\R function, which is licensed under GPL (>= 2)\nwith 'The R Core Team' as the copyright holder.\n}\n"
  },
  {
    "path": "man/future_by.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/future_by.R\n\\name{future_by}\n\\alias{future_by}\n\\title{Apply a Function to a Data Frame Split by Factors via Futures}\n\\usage{\nfuture_by(\n  data,\n  INDICES,\n  FUN,\n  ...,\n  simplify = TRUE,\n  future.envir = parent.frame()\n)\n}\n\\arguments{\n\\item{data}{An \\R object, normally a data frame, possibly a matrix.}\n\n\\item{INDICES}{A factor or a list of factors, each of length \\code{nrow(data)}.}\n\n\\item{FUN}{a function to be applied to (usually data-frame) subsets of \\code{data}.}\n\n\\item{simplify}{logical: see \\code{\\link[base:tapply]{base::tapply()}}.}\n\n\\item{future.envir}{An \\link{environment} passed as argument \\code{envir} to\n\\code{\\link[future:future]{future::future()}} as-is.}\n\n\\item{\\ldots}{Additional arguments pass to \\code{\\link[=future_lapply]{future_lapply()}} and\nthen to \\code{FUN()}.}\n}\n\\value{\nAn object of class \"by\", giving the results for each subset.\nThis is always a list if simplify is false, otherwise a list\nor array (see \\code{\\link[base:tapply]{base::tapply()}}).\nSee also \\code{\\link[base:by]{base::by()}} for details.\n}\n\\description{\nApply a Function to a Data Frame Split by Factors via Futures\n}\n\\details{\nInternally, \\code{data} is grouped by \\code{INDICES} into a list of \\code{data}\nsubset elements which is then processed by \\code{\\link[=future_lapply]{future_lapply()}}.\nWhen the groups differ significantly in size, the processing time\nmay differ significantly between the groups.\nTo correct for processing-time imbalances, adjust the amount of chunking\nvia arguments \\code{future.scheduling} and \\code{future.chunk.size}.\n}\n\\section{Note on 'stringsAsFactors'}{\n\nThe \\code{future_by()} is modeled as closely as possible to the\nbehavior of \\code{base::by()}.  Both functions have \"default\" S3 methods that\ncalls \\code{data <- as.data.frame(data)} internally.  This call may in turn call\nan S3 method for \\code{as.data.frame()} that coerces strings to factors or not\ndepending on whether it has a \\code{stringsAsFactors} argument and what its\ndefault is.\nFor example, the S3 method of \\code{as.data.frame()} for lists changed its\n(effective) default from \\code{stringsAsFactors = TRUE} to\n\\code{stringsAsFactors = TRUE} in R 4.0.0.\n}\n\n\\examples{\n## ---------------------------------------------------------\n## by()\n## ---------------------------------------------------------\nlibrary(datasets) ## warpbreaks\nlibrary(stats)    ## lm()\n\ny0 <- by(warpbreaks, warpbreaks[,\"tension\"],\n         function(x) lm(breaks ~ wool, data = x))\n\nplan(multisession)\ny1 <- future_by(warpbreaks, warpbreaks[,\"tension\"],\n                function(x) lm(breaks ~ wool, data = x))\n\nplan(sequential)\ny2 <- future_by(warpbreaks, warpbreaks[,\"tension\"],\n                function(x) lm(breaks ~ wool, data = x))\n}\n"
  },
  {
    "path": "man/future_kernapply.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/future_kernapply.R\n\\name{future_kernapply}\n\\alias{future_kernapply}\n\\alias{future_kernapply.default}\n\\alias{future_kernapply.ts}\n\\title{Apply Smoothing Kernel in Parallel}\n\\usage{\nfuture_kernapply(x, ...)\n\n\\method{future_kernapply}{default}(x, k, circular = FALSE, ...)\n\n\\method{future_kernapply}{ts}(x, k, circular = FALSE, ...)\n}\n\\arguments{\n\\item{x}{an input vector, matrix, time series or kernel to be smoothed.}\n\n\\item{...}{arguments passed to or from other methods.}\n\n\\item{k}{smoothing \\code{\"tskernel\"} object.}\n\n\\item{circular}{a logical indicating whether the input sequence to be\n    smoothed is treated as circular, i.e., periodic.}\n}\n\\value{\nSee \\code{\\link[stats:kernapply]{stats::kernapply()}} for details.\n}\n\\description{\n\\code{future_kernapply()} is a futurized version of\n\\code{\\link[stats:kernapply]{stats::kernapply()}}, i.e. it computes, in parallel, the\nconvolution between an input sequence and a specific kernel.\nParallelization takes place over columns when \\code{x} is a matrix,\nincluding a \\code{ts} matrix.\n}\n\\examples{\nlibrary(datasets)\nlibrary(stats)\n\nX <- EuStockMarkets[, 1:2]\nk <- kernel(\"daniell\", 50)  # a long moving average\nX_smooth <- future_kernapply(X, k = k)\n\n}\n"
  },
  {
    "path": "man/future_lapply.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/future_eapply.R, R/future_lapply.R,\n%   R/future_replicate.R, R/future_sapply.R, R/future_tapply.R,\n%   R/future_vapply.R\n\\name{future_eapply}\n\\alias{future_eapply}\n\\alias{future_lapply}\n\\alias{future_replicate}\n\\alias{future_sapply}\n\\alias{future_tapply}\n\\alias{future_vapply}\n\\title{Apply a Function over a List or Vector via Futures}\n\\usage{\nfuture_eapply(\n  env,\n  FUN,\n  ...,\n  all.names = FALSE,\n  USE.NAMES = TRUE,\n  future.envir = parent.frame(),\n  future.label = \"future_eapply-\\%d\"\n)\n\nfuture_lapply(\n  X,\n  FUN,\n  ...,\n  future.envir = parent.frame(),\n  future.stdout = TRUE,\n  future.conditions = \"condition\",\n  future.globals = TRUE,\n  future.packages = NULL,\n  future.seed = FALSE,\n  future.scheduling = 1,\n  future.chunk.size = NULL,\n  future.label = \"future_lapply-\\%d\"\n)\n\nfuture_replicate(\n  n,\n  expr,\n  simplify = \"array\",\n  future.seed = TRUE,\n  ...,\n  future.envir = parent.frame(),\n  future.label = \"future_replicate-\\%d\"\n)\n\nfuture_sapply(\n  X,\n  FUN,\n  ...,\n  simplify = TRUE,\n  USE.NAMES = TRUE,\n  future.envir = parent.frame(),\n  future.label = \"future_sapply-\\%d\"\n)\n\nfuture_tapply(\n  X,\n  INDEX,\n  FUN = NULL,\n  ...,\n  default = NA,\n  simplify = TRUE,\n  future.envir = parent.frame(),\n  future.label = \"future_tapply-\\%d\"\n)\n\nfuture_vapply(\n  X,\n  FUN,\n  FUN.VALUE,\n  ...,\n  USE.NAMES = TRUE,\n  future.envir = parent.frame(),\n  future.label = \"future_vapply-\\%d\"\n)\n}\n\\arguments{\n\\item{env}{An \\R environment.}\n\n\\item{FUN}{A function taking at least one argument.}\n\n\\item{all.names}{If \\code{TRUE}, the function will also be applied to variables\nthat start with a period (\\code{.}), otherwise not.\nSee \\code{\\link[base:eapply]{base::eapply()}} for details.}\n\n\\item{USE.NAMES}{See \\code{\\link[base:lapply]{base::sapply()}}.}\n\n\\item{future.envir}{An \\link{environment} passed as argument \\code{envir} to\n\\code{\\link[future:future]{future::future()}} as-is.}\n\n\\item{future.label}{If a character string, then each future is assigned\na label \\code{sprintf(future.label, chunk_idx)}.  If TRUE, then the\nsame as \\code{future.label = \"future_lapply-\\%d\"}.  If FALSE, no labels\nare assigned.}\n\n\\item{X}{An \\R object for which a \\code{\\link[base]{split}} method\nexists.  Typically vector-like, allowing subsetting with\n\\code{\\link[base]{[}}, or a data frame.}\n\n\\item{future.stdout}{If \\code{TRUE} (default), then the standard output of the\nunderlying futures is captured, and re-outputted as soon as possible.\nIf \\code{FALSE}, any output is silenced (by sinking it to the null device\nas it is outputted).\nIf \\code{NA} (not recommended), output is \\emph{not} intercepted.}\n\n\\item{future.conditions}{A character string of conditions classes to be\ncaptured and relayed.  The default is the same as the \\code{condition}\nargument of \\code{\\link[future:Future-class]{future::Future()}}.\nTo not intercept conditions, use \\code{conditions = character(0L)}.\nErrors are always relayed.}\n\n\\item{future.globals}{A logical, a character vector, or a named list for\ncontrolling how globals are handled. For details, see below section.}\n\n\\item{future.packages}{(optional) a character vector specifying packages\nto be attached in the R environment evaluating the future.}\n\n\\item{future.seed}{A logical or an integer (of length one or seven),\nor a list of \\code{length(X)} with pre-generated random seeds.\nFor details, see below section.}\n\n\\item{future.scheduling}{Average number of futures (\"chunks\") per worker.\nIf \\code{0.0}, then a single future is used to process all elements\nof \\code{X}.\nIf \\code{1.0} or \\code{TRUE}, then one future per worker is used.\nIf \\code{2.0}, then each worker will process two futures\n(if there are enough elements in \\code{X}).\nIf \\code{Inf} or \\code{FALSE}, then one future per element of\n\\code{X} is used.\nOnly used if \\code{future.chunk.size} is \\code{NULL}.}\n\n\\item{future.chunk.size}{The average number of elements per future (\"chunk\").\nIf \\code{Inf}, then all elements are processed in a single future.\nIf \\code{NULL}, then argument \\code{future.scheduling} is used.}\n\n\\item{n}{The number of replicates.}\n\n\\item{expr}{An \\R expression to evaluate repeatedly.}\n\n\\item{simplify}{See \\code{\\link[base:lapply]{base::sapply()}} and \\code{\\link[base:tapply]{base::tapply()}}, respectively.}\n\n\\item{INDEX}{A list of one or more factors, each of same length as \\code{X}.\nThe elements are coerced to \\code{\\link[base]{factor}}s by\n\\code{\\link[base:as.factor]{as.factor()}}. Can also be a formula, which\nis useful if \\code{X} is a data frame; see the \\code{f} argument in\n\\code{\\link[base:split]{split()}} for interpretation.}\n\n\\item{default}{See \\code{\\link[base:tapply]{base::tapply()}}.}\n\n\\item{FUN.VALUE}{A template for the required return value from\neach \\code{FUN(X[ii], ...)}.\nTypes may be promoted to a higher type within the ordering\nlogical < integer < double < complex, but not demoted.\nSee \\code{\\link[base:lapply]{base::vapply()}} for details.}\n\n\\item{\\ldots}{(optional) Additional arguments passed to \\code{FUN()}.\nFor \\code{future_*apply()} functions and \\code{replicate()}, any \\verb{future.*} arguments\npart of \\ldots are passed on to \\code{future_lapply()} used internally.\nImportantly, if this is called inside another function which also declares\n\\ldots arguments, do not forget to explicitly pass such \\ldots arguments\ndown to the \\code{future_*apply()} function too, which will then pass them on\nto \\code{FUN()}. See below for an example.}\n}\n\\value{\nA named (unless \\code{USE.NAMES = FALSE}) list.\nSee \\code{\\link[base:eapply]{base::eapply()}} for details.\n\nFor \\code{future_lapply()}, a list with same length and names as \\code{X}.\nSee \\code{\\link[base:lapply]{base::lapply()}} for details.\n\n\\code{future_replicate()} is a wrapper around \\code{future_sapply()} and return\nsimplified object according to the \\code{simplify} argument.\nSee \\code{\\link[base:lapply]{base::replicate()}} for details.\nSince \\code{future_replicate()} usually involves random number generation (RNG),\nit uses \\code{future.seed = TRUE} by default in order produce sound random\nnumbers regardless of future backend and number of background workers used.\n\nFor \\code{future_sapply()}, a vector with same length and names as \\code{X}.\nSee \\code{\\link[base:lapply]{base::sapply()}} for details.\n\n\\code{future_tapply()} returns an array with mode \\code{\"list\"}, unless\n\\code{simplify = TRUE} (default) \\emph{and} \\code{FUN} returns a scalar, in which\ncase the mode of the array is the same as the returned scalars.\nSee \\code{\\link[base:tapply]{base::tapply()}} for details.\n\nFor \\code{future_vapply()}, a vector with same length and names as \\code{X}.\nSee \\code{\\link[base:lapply]{base::vapply()}} for details.\n}\n\\description{\n\\code{future_lapply()} implements \\code{\\link[base:lapply]{base::lapply()}} using futures with perfect\nreplication of results, regardless of future backend used.\nAnalogously, this is true for all the other \\code{future_nnn()} functions.\n}\n\\section{Global variables}{\n\nArgument \\code{future.globals} may be used to control how globals\nshould be handled similarly to how the \\code{globals} argument is used with\n\\code{future()}.\nSince all function calls use the same set of globals, this function can do\nany gathering of globals upfront (once), which is more efficient than if\nit would be done for each future independently.\nIf \\code{TRUE} (default), then globals are automatically identified and gathered.\nIf a character vector of names is specified, then those globals are gathered.\nIf a named list, then those globals are used as is.\nIn all cases, \\code{FUN} and any \\ldots arguments are automatically\npassed as globals to each future created as they are always needed.\n}\n\n\\section{Reproducible random number generation (RNG)}{\n\nUnless \\code{future.seed} is \\code{FALSE} or \\code{NULL}, this function guarantees to\ngenerate the exact same sequence of random numbers \\emph{given the same initial\nseed / RNG state} - this regardless of type of futures, scheduling\n(\"chunking\") strategy, and number of workers.\n\nRNG reproducibility is achieved by pregenerating the random seeds for all\niterations (over \\code{X}) by using parallel RNG streams.  In each\niteration, these seeds are set before calling \\code{FUN(X[[ii]], ...)}.\n\\emph{Note, for large \\code{length(X)} this may introduce a large overhead.}\n\nIf \\code{future.seed = TRUE}, then \\code{\\link[base:Random]{.Random.seed}}\nis used if it holds a parallel RNG seed, otherwise one is created\nrandomly.\n\nIf \\code{future.seed = FALSE}, it is expected that none of the\n\\code{FUN(X[[ii]], ...)} function calls use random number generation.\nIf they do, then an informative warning or error is produced depending\non settings. See \\code{\\link[future:future]{future::future()}} for more details.\nUsing \\code{future.seed = NULL}, is like \\code{future.seed = FALSE} but without\nthe check whether random numbers were generated or not.\n\nAs input, \\code{future.seed} may also take a fixed initial seed (integer),\neither as a full parallel RNG seed, or as a seed generating such a\nfull parallel seed. This seed will be used to generated \\code{length(X)}\nparallel RNG streams.\n\nIn addition to the above, it is possible to specify a pre-generated\nsequence of RNG seeds as a list such that\n\\code{length(future.seed) == length(X)} and where each element is an\ninteger seed vector that can be assigned to\n\\code{\\link[base:Random]{.Random.seed}}.  One approach to generate a\nset of valid RNG seeds based on fixed initial seed (here \\code{42L}) is:\n\n\\if{html}{\\out{<div class=\"sourceCode r\">}}\\preformatted{seeds <- future_lapply(seq_along(X), FUN = function(x) .Random.seed,\n                       future.chunk.size = Inf, future.seed = 42L)\n}\\if{html}{\\out{</div>}}\n\n\\strong{Note that \\code{as.list(seq_along(X))} is \\emph{not} a valid set of such\n\\code{.Random.seed} values.}\n\nIn all cases but \\code{future.seed = FALSE} and \\code{NULL}, the RNG state of the\ncalling R processes after this function returns is guaranteed to be\n\"forwarded one step\" from the RNG state that was before the call and\nin the same way regardless of \\code{future.seed}, \\code{future.scheduling}\nand future strategy used.  This is done in order to guarantee that an \\R\nscript calling \\code{future_lapply()} multiple times should be numerically\nreproducible given the same initial seed.\n}\n\n\\section{Load balancing (\"chunking\")}{\n\nWhether load balancing (\"chunking\") should take place or not can be\ncontrolled by specifying either argument\n\\verb{future.scheduling = <ratio>} or \\verb{future.chunk.size = <count>}.\n\nThe value \\code{future.chunk.size} specifies the average number of elements\nprocessed per future (\"chunks\").\nIf \\code{+Inf}, then all elements are processed in a single future (one worker).\nIf \\code{NULL}, then argument \\code{future.scheduling} is used.\n\nThe value \\code{future.scheduling} specifies the average number of futures\n(\"chunks\") that each worker processes.\nIf \\code{0.0}, then a single future is used to process all iterations;\nnone of the other workers are not used.\nIf \\code{1.0} or \\code{TRUE}, then one future per worker is used.\nIf \\code{2.0}, then each worker will process two futures (if there are\nenough iterations).\nIf \\code{+Inf} or \\code{FALSE}, then one future per iteration is used.\nThe default value is \\code{scheduling = 1.0}.\n}\n\n\\section{Control processing order of elements}{\n\nAttribute \\code{ordering} of \\code{future.chunk.size} or \\code{future.scheduling} can\nbe used to control the ordering the elements are iterated over, which\nonly affects the processing order and \\emph{not} the order values are returned.\nThis attribute can take the following values:\n\\itemize{\n\\item index vector - a numeric vector of length \\code{length(X)}\n\\item function     - a function taking one argument which is called as\n\\code{ordering(length(X))} and which must return an\nindex vector of length \\code{length(X)}, e.g.\n\\code{function(n) rev(seq_len(n))} for reverse ordering.\n\\item \\code{\"random\"}   - this will randomize the ordering via random index\nvector \\code{sample.int(length(X))}.\n}\n\nFor example, \\code{future.scheduling = structure(TRUE, ordering = \"random\")}.\n\\emph{Note}, when elements are processed out of order, then captured standard\noutput and conditions are relayed in that order as well.\n}\n\n\\examples{\n## ---------------------------------------------------------\n## lapply(), sapply(), tapply()\n## ---------------------------------------------------------\nx <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE, FALSE, FALSE, TRUE))\ny0 <- lapply(x, FUN = quantile, probs = 1:3/4)\ny1 <- future_lapply(x, FUN = quantile, probs = 1:3/4)\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\ny0 <- sapply(x, FUN = quantile)\ny1 <- future_sapply(x, FUN = quantile)\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\ny0 <- vapply(x, FUN = quantile, FUN.VALUE = double(5L))\ny1 <- future_vapply(x, FUN = quantile, FUN.VALUE = double(5L))\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\n\n## ---------------------------------------------------------\n## Parallel Random Number Generation\n## ---------------------------------------------------------\n\\donttest{\n## Regardless of the future plan, the number of workers, and\n## where they are, the random numbers produced are identical\n\nplan(multisession)\nset.seed(0xBEEF)\ny1 <- future_lapply(1:5, FUN = rnorm, future.seed = TRUE)\nstr(y1)\n\nplan(sequential)\nset.seed(0xBEEF)\ny2 <- future_lapply(1:5, FUN = rnorm, future.seed = TRUE)\nstr(y2)\n\nstopifnot(all.equal(y1, y2))\n}\n\n\n## ---------------------------------------------------------\n## Process chunks of data.frame rows in parallel\n## ---------------------------------------------------------\niris <- datasets::iris\nchunks <- split(iris, seq(1, nrow(iris), length.out = 3L))\ny0 <- lapply(chunks, FUN = function(iris) sum(iris$Sepal.Length))\ny0 <- do.call(sum, y0)\ny1 <- future_lapply(chunks, FUN = function(iris) sum(iris$Sepal.Length))\ny1 <- do.call(sum, y1)\nprint(y1)\nstopifnot(all.equal(y1, y0))\n\n\n## ---------------------------------------------------------\n## Remember to pass down '...' arguments\n## ---------------------------------------------------------\n## It is important that we don't use '...' as a global variable,\n## as attempted in the following not_okay_fcn()\nbad_fcn <- function(X, ...) {\n  y <- future_lapply(X, FUN = function(x) {\n    mean(x, ...)  ## here '...' is a global variable\n  })\n  y\n}\n\n## Instead, make sure to pass '...' via arguments all the way through\ngood_fcn <- function(X, ...) { ## outer '...'\n  y <- future_lapply(X, FUN = function(x, ...) {\n    mean(x, ...)  ## here '...' is an argument of FUN()\n  }, ...) ## pass outer '...' to FUN()\n  y\n}\n\n\n\\dontshow{\n## R CMD check: make sure any open connections are closed afterward\nif (!inherits(plan(), \"sequential\")) plan(sequential)\n}\n}\n\\author{\nThe implementations of \\code{future_replicate()}, \\code{future_sapply()}, and\n\\code{future_tapply()} are adopted from the source code of the corresponding\nbase \\R functions, which are licensed under GPL (>= 2) with\n'The R Core Team' as the copyright holder.\n}\n\\keyword{iteration}\n\\keyword{manip}\n\\keyword{programming}\n"
  },
  {
    "path": "man/future_mapply.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/future_Filter.R, R/future_Map.R,\n%   R/future_mapply.R\n\\name{future_Filter}\n\\alias{future_Filter}\n\\alias{future_Map}\n\\alias{future_mapply}\n\\alias{future_.mapply}\n\\title{Apply a Function to Multiple List or Vector Arguments}\n\\usage{\nfuture_Filter(f, x, ...)\n\nfuture_Map(\n  f,\n  ...,\n  future.envir = parent.frame(),\n  future.label = \"future_Map-\\%d\"\n)\n\nfuture_mapply(\n  FUN,\n  ...,\n  MoreArgs = NULL,\n  SIMPLIFY = TRUE,\n  USE.NAMES = TRUE,\n  future.envir = parent.frame(),\n  future.stdout = TRUE,\n  future.conditions = \"condition\",\n  future.globals = TRUE,\n  future.packages = NULL,\n  future.seed = FALSE,\n  future.scheduling = 1,\n  future.chunk.size = NULL,\n  future.label = \"future_mapply-\\%d\"\n)\n\nfuture_.mapply(FUN, dots, MoreArgs, ..., future.label = \"future_.mapply-\\%d\")\n}\n\\arguments{\n\\item{f}{A function of the arity \\eqn{k} if \\code{future_Map()} is called with\n\\eqn{k} arguments.}\n\n\\item{x}{A vector-like object to iterate over.}\n\n\\item{future.envir}{An \\link{environment} passed as argument \\code{envir} to\n\\code{\\link[future:future]{future::future()}} as-is.}\n\n\\item{future.label}{If a character string, then each future is assigned\na label \\code{sprintf(future.label, chunk_idx)}.  If TRUE, then the\nsame as \\code{future.label = \"future_lapply-\\%d\"}.  If FALSE, no labels\nare assigned.}\n\n\\item{FUN}{A function to apply, found via \\code{\\link[base:match.fun]{base::match.fun()}}.}\n\n\\item{MoreArgs}{A list of other arguments to \\code{FUN}.}\n\n\\item{SIMPLIFY}{A logical or character string; attempt to reduce the\nresult to a vector, matrix or higher dimensional array; see the simplify\nargument of \\code{\\link[base:lapply]{base::sapply()}}.}\n\n\\item{USE.NAMES}{A logical; use names if the first \\ldots argument has\nnames, or if it is a character vector, use that character vector as the\nnames.}\n\n\\item{future.stdout}{If \\code{TRUE} (default), then the standard output of the\nunderlying futures is captured, and re-outputted as soon as possible.\nIf \\code{FALSE}, any output is silenced (by sinking it to the null device\nas it is outputted).\nIf \\code{NA} (not recommended), output is \\emph{not} intercepted.}\n\n\\item{future.conditions}{A character string of conditions classes to be\ncaptured and relayed.  The default is the same as the \\code{condition}\nargument of \\code{\\link[future:Future-class]{future::Future()}}.\nTo not intercept conditions, use \\code{conditions = character(0L)}.\nErrors are always relayed.}\n\n\\item{future.globals}{A logical, a character vector, or a named list for\ncontrolling how globals are handled.\nFor details, see \\code{\\link[=future_lapply]{future_lapply()}}.}\n\n\\item{future.packages}{(optional) a character vector specifying packages\nto be attached in the R environment evaluating the future.}\n\n\\item{future.seed}{A logical or an integer (of length one or seven), or\na list of \\code{max(lengths(list(...)))} with pre-generated random seeds.\nFor details, see \\code{\\link[=future_lapply]{future_lapply()}}.}\n\n\\item{future.scheduling}{Average number of futures (\"chunks\") per worker.\nIf \\code{0.0}, then a single future is used to process all elements\nof \\code{X}.\nIf \\code{1.0} or \\code{TRUE}, then one future per worker is used.\nIf \\code{2.0}, then each worker will process two futures\n(if there are enough elements in \\code{X}).\nIf \\code{Inf} or \\code{FALSE}, then one future per element of\n\\code{X} is used.\nOnly used if \\code{future.chunk.size} is \\code{NULL}.}\n\n\\item{future.chunk.size}{The average number of elements per future (\"chunk\").\nIf \\code{Inf}, then all elements are processed in a single future.\nIf \\code{NULL}, then argument \\code{future.scheduling} is used.}\n\n\\item{dots}{A list of arguments to vectorize over (vectors or lists of\nstrictly positive length, or all of zero length).}\n\n\\item{\\ldots}{Arguments to vectorize over, will be recycled to common\nlength, or zero if one of them is of length zero.}\n}\n\\value{\nSee \\link[=Filter]{base::Filter()} for details.\n\n\\code{future_Map()} is a simple wrapper to \\code{future_mapply()} which does not\nattempt to simplify the result.\nSee \\link[=Map]{base::Map()} for details.\n\n\\code{future_mapply()} returns a list, or for \\code{SIMPLIFY = TRUE}, a vector,\narray or list.  See \\code{\\link[base:mapply]{base::mapply()}} for details.\n\n\\code{future_.mapply()} returns a list. See \\code{\\link[base:mapply]{base::.mapply()}} for details.\n}\n\\description{\n\\code{future_mapply()} implements \\code{\\link[base:mapply]{base::mapply()}} using futures with perfect\nreplication of results, regardless of future backend used.\nAnalogously to \\code{mapply()}, \\code{future_mapply()} is a multivariate version of\n\\code{future_sapply()}.\nIt applies \\code{FUN} to the first elements of each \\ldots argument,\nthe second elements, the third elements, and so on.\nArguments are recycled if necessary.\n}\n\\details{\nNote that \\code{\\link[base:mapply]{base::.mapply()}}, which \\code{future_.mapply()} is modeled after\nis listed as an \"internal\" function in \\R despite being exported.\n}\n\\examples{\n## ---------------------------------------------------------\n## Filter()\n## ---------------------------------------------------------\nis_even <- function(x) { x \\%\\% 2 == 0 }\nx <- sample.int(100, size = 1000, replace = TRUE)\ny <- future_Filter(is_even, x)\n\n\n## ---------------------------------------------------------\n## mapply()\n## ---------------------------------------------------------\ny0 <- mapply(rep, 1:4, 4:1)\ny1 <- future_mapply(rep, 1:4, 4:1)\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(rep, times = 1:4, x = 4:1)\ny1 <- future_mapply(rep, times = 1:4, x = 4:1)\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(rep, times = 1:4, MoreArgs = list(x = 42))\ny1 <- future_mapply(rep, times = 1:4, MoreArgs = list(x = 42))\nstopifnot(identical(y1, y0))\n\ny0 <- mapply(function(x, y) seq_len(x) + y,\n             c(a =  1, b = 2, c = 3),  # names from first\n             c(A = 10, B = 0, C = -10))\ny1 <- future_mapply(function(x, y) seq_len(x) + y,\n                    c(a =  1, b = 2, c = 3),  # names from first\n                    c(A = 10, B = 0, C = -10))\nstopifnot(identical(y1, y0))\n\nword <- function(C, k) paste(rep.int(C, k), collapse = \"\")\ny0 <- mapply(word, LETTERS[1:6], 6:1, SIMPLIFY = FALSE)\ny1 <- future_mapply(word, LETTERS[1:6], 6:1, SIMPLIFY = FALSE)\nstopifnot(identical(y1, y0))\n\n\n## ---------------------------------------------------------\n## Parallel Random Number Generation\n## ---------------------------------------------------------\n\\donttest{\n## Regardless of the future plan, the number of workers, and\n## where they are, the random numbers produced are identical\n\nplan(multisession)\nset.seed(0xBEEF)\ny1 <- future_mapply(stats::runif, n = 1:4, max = 2:5,\n                    MoreArgs = list(min = 1), future.seed = TRUE)\nprint(y1)\n\nplan(sequential)\nset.seed(0xBEEF)\ny2 <- future_mapply(stats::runif, n = 1:4, max = 2:5,\n                    MoreArgs = list(min = 1), future.seed = TRUE)\nprint(y2)\n\nstopifnot(all.equal(y1, y2))\n}\n\n\\dontshow{\n## R CMD check: make sure any open connections are closed afterward\nif (!inherits(plan(), \"sequential\")) plan(sequential)\n}\n}\n\\author{\nThe implementation of \\code{future_Filter()} is adopted from the source code\nof the corresponding base \\R function \\code{Filter()}, which is licensed under\nGPL (>= 2) with 'The R Core Team' as the copyright holder.\n\nThe implementation of \\code{future_Map()} is adopted from the source code\nof the corresponding base \\R function \\code{Map()}, which is licensed under\nGPL (>= 2) with 'The R Core Team' as the copyright holder.\n}\n\\keyword{iteration}\n\\keyword{manip}\n\\keyword{programming}\n"
  },
  {
    "path": "man/makeChunks.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/makeChunks.R\n\\name{makeChunks}\n\\alias{makeChunks}\n\\title{Create Chunks of Index Vectors}\n\\usage{\nmakeChunks(\n  nbrOfElements,\n  nbrOfWorkers,\n  future.scheduling = 1,\n  future.chunk.size = NULL\n)\n}\n\\arguments{\n\\item{nbrOfElements}{(integer) Total number of elements to iterate over.}\n\n\\item{nbrOfWorkers}{(integer) Number of workers available.}\n\n\\item{future.scheduling}{(numeric) A strictly positive scalar.\nOnly used if argument \\code{future.chunk.size} is \\code{NULL}.}\n\n\\item{future.chunk.size}{(numeric) The maximum number of elements per\nchunk, or \\code{NULL}.  If \\code{NULL}, then the chunk sizes are given by the\n\\code{future.scheduling} argument.}\n}\n\\value{\nA list of chunks, where each chunk is an integer vector of\nunique indices \\code{[1, nbrOfElements]}.  The union of all chunks\nholds \\code{nbrOfElements} elements and equals \\code{1:nbrOfElements}.\nIf \\code{nbrOfElements == 0}, then an empty list is returned.\n}\n\\description{\n\\emph{This is an internal function.}\n}\n\\section{Control processing order of elements}{\n\nAttribute \\code{ordering} of \\code{future.chunk.size} or \\code{future.scheduling} can\nbe used to control the ordering the elements are iterated over, which\nonly affects the processing order \\emph{not} the order values are returned.\nThis attribute can take the following values:\n\\itemize{\n\\item index vector - a numeric vector of length \\code{nbrOfElements} specifying\nhow elements are remapped\n\\item function     - a function taking one argument which is called as\n\\code{ordering(nbrOfElements)} and which must return an\nindex vector of length \\code{nbrOfElements}, e.g.\n\\code{function(n) rev(seq_len(n))} for reverse ordering.\n\\item \\code{\"random\"}   - this will randomize the ordering via random index\nvector \\code{sample.int(nbrOfElements)}.\n}\n}\n\n\\keyword{internal}\n"
  },
  {
    "path": "pkgdown/_pkgdown.yml",
    "content": "url: https://future.apply.futureverse.org\n\nhome:\n  links:\n  - text: Roadmap/Milestones\n    href: https://github.com/futureverse/future.apply/milestones\n  - text: The Futureverse Project\n    href: https://www.futureverse.org/\n  - text: Futureverse User Forum\n    href: https://github.com/futureverse/future/discussions\n\nnavbar:\n  structure:\n    right: [search, futureverse, pkgs, cran, github, lightswitch]\n  components:\n    futureverse:\n      icon: fas fa-home\n      href: https://www.futureverse.org/\n    pkgs:\n      text: Packages\n      menu:\n      - text: doFuture (map-reduce)\n        href: https://doFuture.futureverse.org\n      - text: furrr (map-reduce)\n        href: https://furrr.futureverse.org\n      - text: future \n        href: https://future.futureverse.org\n      - text: future.apply (map-reduce)\n        href: https://future.apply.futureverse.org\n      - text: future.batchtools (backend)\n        href: https://future.batchtools.futureverse.org\n      - text: future.callr (backend)\n        href: https://future.callr.futureverse.org\n      - text: future.mirai (backend)\n        href: https://future.mirai.futureverse.org\n      - text: future.tests \n        href: https://future.tests.futureverse.org\n      - text: futurize (map-reduce)\n        href: https://futurize.futureverse.org\n      - text: globals \n        href: https://globals.futureverse.org\n      - text: listenv \n        href: https://listenv.futureverse.org\n      - text: parallelly \n        href: https://parallelly.futureverse.org\n      - text: progressr \n        href: https://progressr.futureverse.org\n      - text: future.p2p (experimental)\n        href: https://future.p2p.futureverse.org\n      - text: future.tools (experimental)\n        href: https://future.tools.futureverse.org\n      - text: marshal (experimental)\n        href: https://marshal.futureverse.org\n    cran:\n      icon: fab fa-r-project\n      href: https://cloud.r-project.org/package=future.apply\n      \nsearch:\n  exclude: ['README_ja.md']\n  \ntemplate:\n  params:\n    docsearch:\n      api_key: aa6e02fc501886fb0f7c91ac4e300456\n      index_name: futureverse\n      algoliaOptions: { 'facetFilters': ['project:future.apply'] }\n    ganalytics: G-SB3EQSD9FR\n  bootstrap: 5\n  light-switch: true\n"
  },
  {
    "path": "pkgdown/_pkgdown.yml.rsp",
    "content": "<%\npkgs_mapreduce <- c(\"futurize\", \"future.apply\", \"doFuture\", \"furrr\")\npkgs_backend <- c(\"future.batchtools\", \"future.callr\", \"future.mirai\")\npkgs <- c(\"globals\", \"listenv\", \"parallelly\", \"future\", \"future.tests\", \"progressr\", pkgs_mapreduce, pkgs_backend)\npkgs_extra <- c(\"future.p2p\", \"future.tools\", \"marshal\")\npkgs <- c(sort(pkgs), pkgs_extra)\nurls <- sprintf(\"https://%s.futureverse.org\", pkgs)\nnames(urls) <- pkgs\n\nfile <- file.path(c(\".\", \"..\"), \"DESCRIPTION\")\nfile <- file[utils::file_test(\"-f\", file)]\npkg <- read.dcf(file)[,\"Package\"]\n%>\nurl: https://<%= pkg %>.futureverse.org\n\nhome:\n  links:\n  - text: Roadmap/Milestones\n    href: https://github.com/<%= gsub(\"(^.*:|[.]git$)\", \"\", subset(gert::git_remote_list(), name == \"origin\")$url) %>/milestones\n  - text: The Futureverse Project\n    href: https://www.futureverse.org/\n  - text: Futureverse User Forum\n    href: https://github.com/futureverse/future/discussions\n\nnavbar:\n  structure:\n    right: [search, futureverse, pkgs, cran, github, lightswitch]\n  components:\n    futureverse:\n      icon: fas fa-home\n      href: https://www.futureverse.org/\n    pkgs:\n      text: Packages\n      menu:\n<% for (name in names(urls)) { %>\n      - text: <%= name %> <% if (name %in% pkgs_extra) { %>(experimental)<% } else if (name %in% pkgs_backend) { %>(backend)<% } else if (name %in% pkgs_mapreduce) { %>(map-reduce)<% } %>\n        href: <%= urls[name] %>\n<% } %>\n    cran:\n      icon: fab fa-r-project\n      href: https://cloud.r-project.org/package=<%= pkg %>\n      \nsearch:\n  exclude: ['README_ja.md']\n  \ntemplate:\n  params:\n    docsearch:\n      api_key: aa6e02fc501886fb0f7c91ac4e300456\n      index_name: futureverse\n      algoliaOptions: { 'facetFilters': ['project:<%= pkg %>'] }\n    ganalytics: G-SB3EQSD9FR\n  bootstrap: 5\n  light-switch: true\n"
  },
  {
    "path": "revdep/README.md",
    "content": "# Platform\n\n|field    |value                                                       |\n|:--------|:-----------------------------------------------------------|\n|version  |R version 4.5.2 (2025-10-31)                                |\n|os       |Rocky Linux 8.10 (Green Obsidian)                           |\n|system   |x86_64, linux-gnu                                           |\n|ui       |X11                                                         |\n|language |en                                                          |\n|collate  |en_US.UTF-8                                                 |\n|ctype    |en_US.UTF-8                                                 |\n|tz       |America/Los_Angeles                                         |\n|date     |2026-02-19                                                  |\n|pandoc   |3.8.3 @ /software/c4/cbi/software/pandoc-3.8.3/bin/pandoc   |\n|quarto   |1.8.26 @ /software/c4/cbi/software/quarto-1.8.26/bin/quarto |\n\n# Dependencies\n\n|package      |old    |new         |Δ  |\n|:------------|:------|:-----------|:--|\n|future.apply |1.20.1 |1.20.1-9006 |*  |\n|codetools    |0.2-20 |0.2-20      |   |\n|digest       |0.6.39 |0.6.39      |   |\n|future       |1.69.0 |1.69.0      |   |\n|globals      |0.19.0 |0.19.0      |   |\n|listenv      |0.10.0 |0.10.0      |   |\n|parallelly   |1.46.1 |1.46.1      |   |\n\n# Revdeps\n\n## All (259)\n\n|package                   |version      |error |warning |note |\n|:-------------------------|:------------|:-----|:-------|:----|\n|aae.pop                   |0.2.0        |      |        |     |\n|[adestr](problems.md#adestr)|1.0.0        |      |        |1    |\n|AgePopDenom               |1.2.3        |      |        |     |\n|AIPW                      |0.6.9.2      |      |        |     |\n|altdoc                    |0.7.1        |      |        |     |\n|ao                        |1.2.2        |      |        |     |\n|ARCHISSUR                 |0.0.1        |      |        |     |\n|arkdb                     |0.0.19       |      |        |     |\n|aroma.cn                  |1.7.1        |      |        |     |\n|BAMBI                     |2.3.6        |      |        |     |\n|BayesianMCPMod            |1.2.0        |      |        |     |\n|bayesics                  |2.0.2        |      |        |     |\n|bayesSSM                  |0.7.1        |      |        |     |\n|bbknnR                    |2.0.2        |      |        |     |\n|bcmaps                    |2.2.1        |      |        |     |\n|BEKKs                     |1.4.6        |      |        |     |\n|bidser                    |0.2.0        |      |        |     |\n|bifrost                   |0.1.3        |      |        |     |\n|bigDM                     |0.5.7        |      |        |     |\n|bigPLSR                   |0.7.2        |      |        |     |\n|bioLeak                   |0.2.0        |      |        |     |\n|bivarhr                   |0.1.5        |      |        |     |\n|blavaan                   |0.5-10       |      |        |     |\n|bolasso                   |0.4.0        |      |        |     |\n|brms                      |2.23.0       |      |        |     |\n|bsitar                    |0.3.2        |      |        |     |\n|bspcov                    |1.0.3        |      |        |     |\n|calmr                     |0.8.1        |      |        |     |\n|canaper                   |1.0.1        |      |        |     |\n|cellGeometry              |0.5.7        |      |        |     |\n|chopin                    |0.9.9        |      |        |     |\n|CimpleG                   |1.0.1        |      |        |     |\n|clickR                    |0.9.45       |      |        |     |\n|[ClustIRR](problems.md#clustirr)|1.8.0        |      |        |2    |\n|codalm                    |0.1.3        |      |        |     |\n|collinear                 |3.0.0        |      |        |     |\n|conformalInference.fd     |1.1.1        |      |        |     |\n|conformalInference.multi  |1.1.2        |      |        |     |\n|couplr                    |1.0.10       |      |        |     |\n|[cSEM](problems.md#csem)  |0.6.1        |      |        |1    |\n|[ctsem](problems.md#ctsem)|3.10.6       |      |2       |     |\n|cvCovEst                  |1.2.2        |      |        |     |\n|DAISIE                    |4.6.0        |      |        |     |\n|datefixR                  |2.0.0        |      |        |     |\n|DeclareDesign             |1.1.0        |      |        |     |\n|deseats                   |1.1.1        |      |        |     |\n|detectXOR                 |0.1.0        |      |        |     |\n|dipsaus                   |0.3.3        |      |        |     |\n|[disk.frame](problems.md#diskframe)|0.8.3        |      |        |1    |\n|distantia                 |2.0.2        |      |        |     |\n|doFuture                  |1.2.0        |      |        |     |\n|DQAstats                  |0.3.9        |      |        |     |\n|DRPT                      |1.1          |      |        |     |\n|drtmle                    |1.1.2        |      |        |     |\n|dsos                      |0.1.2        |      |        |     |\n|DTEAssurance              |1.1.0        |      |        |     |\n|e2tree                    |0.2.0        |      |        |     |\n|EconCausal                |1.0.2        |      |        |     |\n|eCV                       |0.0.2        |      |        |     |\n|[EFAtools](problems.md#efatools)|0.6.1        |      |        |1    |\n|EGAnet                    |2.4.0        |      |        |     |\n|EpiNow2                   |1.8.0        |      |        |     |\n|[fabletools](problems.md#fabletools)|0.6.1        |1     |        |     |\n|fastbioclim               |0.3.0        |      |        |     |\n|FastJM                    |1.5.3        |      |        |     |\n|fdacluster                |0.4.2        |      |        |     |\n|FDOTT                     |0.1.0        |      |        |     |\n|fect                      |2.1.0        |      |        |     |\n|ferrn                     |0.3.0        |      |        |     |\n|fitlandr                  |0.1.1        |      |        |     |\n|flassomsm                 |0.1.0        |      |        |     |\n|[FracFixR](problems.md#fracfixr)|1.0.0        |1     |        |     |\n|fundiversity              |1.1.1        |      |        |     |\n|future.batchtools         |0.21.0       |      |        |     |\n|future.callr              |0.10.2       |      |        |     |\n|future.mirai              |0.10.1       |      |        |     |\n|futureverse               |0.2.0        |      |        |     |\n|futurize                  |0.1.0        |      |        |     |\n|fwb                       |0.5.1        |      |        |     |\n|gammaFuncModel            |6.0          |      |        |     |\n|genBaRcode                |1.2.8        |      |        |     |\n|geocmeans                 |0.3.4        |      |        |     |\n|geohabnet                 |2.2          |      |        |     |\n|GeometricMorphometricsMix |0.6.0.1      |      |        |     |\n|geomeTriD                 |1.4.1        |      |        |     |\n|GeoModels                 |2.2.2        |      |        |     |\n|gooseR                    |0.1.2        |      |        |     |\n|GPCsign                   |0.1.1        |      |        |     |\n|gsDesignTune              |0.1.0        |      |        |     |\n|gstat                     |2.1-5        |      |        |     |\n|gWQS                      |3.0.5        |      |        |     |\n|haldensify                |0.2.8        |      |        |     |\n|hbamr                     |2.4.5        |      |        |     |\n|[hero](problems.md#hero)  |0.6          |      |        |1    |\n|hydroloom                 |1.1.1        |      |        |     |\n|iml                       |0.11.4       |      |        |     |\n|important                 |0.2.1        |      |        |     |\n|incubate                  |1.3.0        |      |        |     |\n|iNEXT.beta3D              |1.0.2        |      |        |     |\n|inlinedocs                |2023.9.4     |      |        |     |\n|ino                       |1.2.0        |      |        |     |\n|[InPAS](problems.md#inpas)|2.18.1       |      |        |3    |\n|InterpolateR              |1.4-3        |      |        |     |\n|isopam                    |3.3          |      |        |     |\n|ivd                       |1.0.0        |      |        |     |\n|[ivmte](problems.md#ivmte)|1.4.0        |      |        |1    |\n|IVPP                      |1.1.1        |      |        |     |\n|jackknifeR                |2.0.0        |      |        |     |\n|JANE                      |2.1.0        |      |        |     |\n|jpinfect                  |2023.2026.02 |      |        |     |\n|[kappaGold](problems.md#kappagold)|0.4.0        |      |        |1    |\n|kernelboot                |0.1.10       |      |        |     |\n|keyATM                    |0.5.5        |      |        |     |\n|kmeRtone                  |1.0          |      |        |     |\n|LandComp                  |0.0.5        |      |        |     |\n|lava                      |1.8.2        |      |        |     |\n|[lavDiag](problems.md#lavdiag)|0.1.0        |1     |        |     |\n|LexFindR                  |1.1.0        |      |        |     |\n|lgr                       |0.5.2        |      |        |     |\n|lightr                    |1.9.0        |      |        |     |\n|LipidMS                   |3.1.2        |      |        |     |\n|LLMR                      |0.6.3        |      |        |     |\n|LTFGRS                    |1.0.1        |      |        |     |\n|LTFHPlus                  |2.2.0        |      |        |     |\n|[MAI](problems.md#mai)    |1.16.0       |      |        |1    |\n|malariaAtlas              |1.6.4        |      |        |     |\n|MAMS                      |3.0.3        |      |        |     |\n|marginaleffects           |0.32.0       |      |        |     |\n|mcmcensemble              |3.2.0        |      |        |     |\n|mcp                       |0.3.4        |      |        |     |\n|MDCcure                   |0.1.0        |      |        |     |\n|merTools                  |0.6.4        |      |        |     |\n|MetaHD                    |0.1.4        |      |        |     |\n|metasnf                   |2.1.2        |      |        |     |\n|[mikropml](problems.md#mikropml)|1.7.0        |      |        |1    |\n|missSBM                   |1.0.5        |      |        |     |\n|mlr3                      |1.4.0        |      |        |     |\n|mlr3db                    |0.7.0        |      |        |     |\n|mlr3summary               |0.1.2        |      |        |     |\n|modelsummary              |2.6.0        |      |        |     |\n|modeltuning               |0.1.3        |      |        |     |\n|modernBoot                |0.1.1        |      |        |     |\n|mongolstats               |0.1.1        |      |        |     |\n|mrgsim.parallel           |0.3.0        |      |        |     |\n|mrIML                     |2.2.0        |      |        |     |\n|mtarm                     |0.1.8        |      |        |     |\n|multivarious              |0.3.1        |      |        |     |\n|nestedcv                  |0.8.0        |      |        |     |\n|NetSimR                   |0.1.5        |      |        |     |\n|neuroim2                  |0.8.5        |      |        |     |\n|nhdplusTools              |1.4.2        |      |        |     |\n|[nixtlar](problems.md#nixtlar)|0.6.2        |      |        |1    |\n|NMAR                      |0.1.2        |      |        |     |\n|normref                   |0.0.0.1      |      |        |     |\n|oeli                      |0.7.5        |      |        |     |\n|opImputation              |0.6          |      |        |     |\n|optic                     |1.0.1        |      |        |     |\n|optimLanduse              |1.2.1        |      |        |     |\n|origami                   |1.0.7        |      |        |     |\n|outliers.ts.oga           |1.1.2        |      |        |     |\n|[OutSeekR](problems.md#outseekr)|1.1.0        |      |        |1    |\n|[PAMpal](problems.md#pampal)|1.4.4        |      |1       |     |\n|[PAMscapes](problems.md#pamscapes)|0.15.0       |      |1       |     |\n|[pavo](problems.md#pavo)  |2.9.0        |      |1       |     |\n|pbapply                   |1.7-4        |      |        |     |\n|PeakSegDisk               |2024.10.1    |      |        |     |\n|penaltyLearning           |2024.9.3     |      |        |     |\n|[pgxRpi](problems.md#pgxrpi)|1.6.0        |      |        |1    |\n|phylolm                   |2.6.5        |      |        |     |\n|phylopath                 |1.3.1        |      |        |     |\n|phyr                      |1.1.3        |      |        |     |\n|PLNmodels                 |1.2.2        |      |        |     |\n|polle                     |1.6.2        |      |        |     |\n|portvine                  |1.0.3        |      |        |     |\n|powergrid                 |0.5.0        |      |        |     |\n|[powRICLPM](problems.md#powriclpm)|0.2.1        |      |        |1    |\n|progressr                 |0.18.0       |      |        |     |\n|[qape](problems.md#qape)  |2.1          |      |        |1    |\n|QBMS                      |2.0.0        |      |        |     |\n|qbrms                     |1.0.1        |      |        |     |\n|[QDNAseq](problems.md#qdnaseq)|1.46.0       |      |1       |     |\n|qgcomp                    |2.18.7       |      |        |     |\n|qgcompint                 |1.0.2        |      |        |     |\n|rangeMapper               |2.0.3        |      |        |     |\n|ravepipeline              |0.0.3        |      |        |     |\n|rBiasCorrection           |0.3.5        |      |        |     |\n|readsdr                   |0.3.0        |      |        |     |\n|readyomics                |0.2.0        |      |        |     |\n|[receptiviti](problems.md#receptiviti)|0.2.1        |1     |        |     |\n|recforest                 |1.0.2        |      |        |     |\n|refineR                   |2.0.0        |      |        |     |\n|restriktor                |0.6-30       |      |        |     |\n|rgeomorphon               |0.3.0        |      |        |     |\n|robotstxt                 |0.7.15       |      |        |     |\n|rSDR                      |1.0.3.0      |      |        |     |\n|[rsi](problems.md#rsi)    |0.3.2        |      |        |1    |\n|Rsolnp                    |2.0.1        |      |        |     |\n|RTransferEntropy          |0.2.21       |      |        |     |\n|s3fs                      |0.1.7        |      |        |     |\n|S3VS                      |1.0          |      |        |     |\n|scDiffCom                 |1.2.0        |      |        |     |\n|SCGLR                     |3.1.0        |      |        |     |\n|scStability               |1.0.3        |      |        |     |\n|sctransform               |0.4.3        |      |        |     |\n|SDModels                  |2.0.2        |      |        |     |\n|sdmTMB                    |1.0.0        |      |        |     |\n|SelectBoost.beta          |0.4.5        |      |        |     |\n|SelectBoost.gamlss        |0.2.2        |      |        |     |\n|semtree                   |0.9.23       |      |        |     |\n|sentopics                 |0.7.6        |      |        |     |\n|seqHMM                    |2.1.0        |      |        |     |\n|SEQTaRget                 |1.3.6        |      |        |     |\n|Seurat                    |5.4.0        |      |        |     |\n|SeuratObject              |5.3.0        |      |        |     |\n|SFHNV                     |0.1.0        |      |        |     |\n|shapr                     |1.0.8        |      |        |     |\n|sharp                     |1.4.8        |      |        |     |\n|Signac                    |1.16.0       |      |        |     |\n|[signeR](problems.md#signer)|2.12.0       |      |        |3    |\n|SimDesign                 |2.23         |      |        |     |\n|simglm                    |0.8.9        |      |        |     |\n|sims                      |0.0.4        |      |        |     |\n|smoots                    |1.1.4        |      |        |     |\n|sNPLS                     |1.0.27       |      |        |     |\n|socialSim                 |0.1.8        |      |        |     |\n|[solitude](problems.md#solitude)|1.1.3        |      |        |1    |\n|spaMM                     |4.6.1        |      |        |     |\n|spatialwarnings           |3.1.1        |      |        |     |\n|[sperrorest](problems.md#sperrorest)|3.0.5        |      |        |1    |\n|spNetwork                 |0.4.4.7      |      |        |     |\n|spStack                   |1.1.2        |      |        |     |\n|squat                     |0.5.0        |      |        |     |\n|stars                     |0.7-1        |      |        |     |\n|stenographer              |1.0.0        |      |        |     |\n|steps                     |1.3.0        |      |        |     |\n|[stppSim](problems.md#stppsim)|1.3.4        |      |1       |     |\n|supercells                |1.0.0        |      |        |     |\n|svycoxme                  |1.0.0        |      |        |     |\n|svytest                   |1.1.0        |      |        |     |\n|targeted                  |0.7.1        |      |        |     |\n|TaxaNorm                  |2.4          |      |        |     |\n|tidySEM                   |0.2.10       |      |        |     |\n|Tivy                      |0.1.1        |      |        |     |\n|[tramvs](problems.md#tramvs)|0.0-8        |      |1       |     |\n|TreeMineR                 |1.0.3        |      |        |     |\n|tsdistributions           |1.0.3        |      |        |     |\n|[tsgarch](problems.md#tsgarch)|1.0.3        |      |        |1    |\n|tsissm                    |1.0.2        |      |        |     |\n|tsmarch                   |1.0.0        |      |        |     |\n|tune                      |2.0.1        |      |        |     |\n|[txshift](problems.md#txshift)|0.3.8        |      |        |1    |\n|vital                     |2.0.3        |      |        |     |\n|wildmeta                  |0.3.2        |      |        |     |\n|winputall                 |1.0.1        |      |        |     |\n|wizaRdry                  |0.6.4        |      |        |     |\n|wqspt                     |1.0.2        |      |        |     |\n|xegaPopulation            |1.0.0.12     |      |        |     |\n|xplainfi                  |1.0.0        |      |        |     |\n|ycevo                     |0.3.0        |      |        |     |\n\n"
  },
  {
    "path": "revdep/cran.md",
    "content": "## revdepcheck results\n\nWe checked 259 reverse dependencies (252 from CRAN + 7 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package.\n\n * We saw 0 new problems\n * We failed to check 0 packages\n\n"
  },
  {
    "path": "revdep/failures.md",
    "content": "*Wow, no problems at all. :)*"
  },
  {
    "path": "revdep/notes.md",
    "content": "# Notes\n\n## Setup\n\n```r\n> options(Ncpus = 6L)\n> install.packages(\"remotes\")\n> remotes::install_github(\"r-lib/revdepcheck\")\n```\n\n```sh\n## Used by R itself\n$ revdep/run.R --preinstall RCurl XML\n```\n\n\n## Pre-installation\n\nIn order to run these checks successfully on a machine _without internet\naccess_, make sure to first populate the 'crancache' cache by pre-installing\nall packages to be tested plus a few more.\n\n```sh\n$ module load jags; revdep/run.R --preinstall runjags\n\n$ module load hdf5; revdep/run.R --preinstall hdf5r\n\n$ module load geos; revdep/run.R --preinstall lwgeom\n\n$ scl enable devtoolset-4 \"revdep/run.R --preinstall blavaan\"\n\n$ scl enable devtoolset-4 \"revdep/run.R --preinstall xgboost\"\n\n$ scl enable devtoolset-4 \"revdep/run.R --preinstall rstanarm\"\n\n# WORKAROUND: https://github.com/pacificclimate/Rudunits2/issues/25\n$ Rscript -e \"crancache::install_packages('udunits2', configure.args='--with-udunits2-include=/usr/include/udunits2')\"\n\n\n## Update current crancache\n$ revdep/run.R --preinstall-update\n\n## All packages to be tested\n$ revdep/run.R --preinstall-children\n```\n\n\nIs this why I'm getting the following error when install the 'stars' package on CentOS 7?\n\n```sh\nldconfig -p | grep geos\n        libgeos_c.so.1 (libc6,x86-64) => /lib64/libgeos_c.so.1\n        libgeos_c.so (libc6,x86-64) => /lib64/libgeos_c.so\n        libgeos-3.4.2.so (libc6,x86-64) => /lib64/libgeos-3.4.2.so\n```\n\n```r\n$ R\nR version 4.0.0 alpha (2020-04-03 r78148)\nCopyright (C) 2020 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu (64-bit)\n...\n\n> packageVersion(\"lwgeom\")\n[1] ‘0.2.1’\n\n> install.packages(\"stars\")\nInstalling package into ‘/wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI’\n(as ‘lib’ is unspecified)\n* installing *source* package ‘stars’ ...\n** package ‘stars’ successfully unpacked and MD5 sums checked\n** using staged installation\n** R\n** demo\n** inst\n** byte-compile and prepare package for lazy loading\nError in dyn.load(file, DLLpath = DLLpath, ...) : \n  unable to load shared object '/wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI/lwgeom/libs/lwgeom.so':\n  /wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI/lwgeom/libs/lwgeom.so: undefined symbol: GEOSClipByRect\nCalls: <Anonymous> ... asNamespace -> loadNamespace -> library.dynam -> dyn.load\n** help\n*** installing help indices\n** building package indices\n** installing vignettes\n** testing if installed package can be loaded from temporary location\nError: package or namespace load failed for ‘stars’ in dyn.load(file, DLLpath = DLLpath, ...):\n unable to load shared object '/wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI/lwgeom/libs/lwgeom.so':\n  /wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI/lwgeom/libs/lwgeom.so: undefined symbol: GEOSClipByRect\nError: loading failed\n** testing if installed package can be loaded from final location\nError: package or namespace load failed for ‘stars’ in dyn.load(file, DLLpath = DLLpath, ...):\n unable to load shared object '/wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI/lwgeom/libs/lwgeom.so':\n  /wynton/home/cbi/hb/R/x86_64-pc-linux-gnu-library/4.0-CBI/lwgeom/libs/lwgeom.so: undefined symbol: GEOSClipByRect\nError: loading failed\n```\n\n"
  },
  {
    "path": "revdep/problems.md",
    "content": "# adestr (1.0.0)\n\n* Email: <mailto:meis@imbi.uni-heidelberg.de>\n* GitHub mirror: <https://github.com/cran/adestr>\n\nRun `revdepcheck::revdep_details(, \"adestr\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n       Missing dependency on R >= 4.1.0 because package code uses the pipe\n       |> or function shorthand \\(...) syntax added in R 4.1.0.\n       File(s) using such syntax:\n         ‘IntervalEstimator-class.Rd’ ‘PValue-class.Rd’\n         ‘PointEstimator-class.Rd’ ‘analyze.R’ ‘estimators.R’\n         ‘evaluate_estimator.R’ ‘fisher_information.R’\n         ‘integrate_over_sample_space.R’ ‘mle_distribution.R’ ‘n2c2_helpers.R’\n         ‘plot.R’ ‘print.R’ ‘reference_implementation.R’\n     ```\n\n# ClustIRR (1.8.0)\n\n* GitHub: <https://github.com/snaketron/ClustIRR>\n* Email: <mailto:simokitanovski@gmail.com>\n\nRun `revdepcheck::revdep_details(, \"ClustIRR\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n     Package listed in more than one of Depends, Imports, Suggests, Enhances:\n       ‘ggplot2’\n     A package should be listed in only one of these fields.\n     ```\n\n*   checking R code for possible problems ... NOTE\n     ```\n     get_ag_gene_hits: no visible binding for global variable ‘cells’\n     get_ag_gene_hits: no visible binding for global variable ‘clones’\n     get_ag_gene_hits: no visible binding for global variable ‘community’\n     get_ag_gene_hits: no visible binding for global variable ‘ag’\n     get_ag_species_hits: no visible binding for global variable ‘cells’\n     get_ag_species_hits: no visible binding for global variable ‘clones’\n     get_ag_species_hits: no visible binding for global variable ‘community’\n     get_ag_species_hits: no visible binding for global variable ‘ag’\n     get_beta_violin: no visible binding for global variable ‘spec’\n     get_beta_violin: no visible binding for global variable ‘size’\n     get_honeycombs: no visible binding for global variable ‘x_adj’\n     get_honeycombs: no visible binding for global variable ‘y_adj’\n     get_honeycombs: no visible binding for global variable ‘..count..’\n     Undefined global functions or variables:\n       ..count.. ag cells clones community size spec x_adj y_adj\n     ```\n\n# cSEM (0.6.1)\n\n* GitHub: <https://github.com/FloSchuberth/cSEM>\n* Email: <mailto:f.schuberth@utwente.nl>\n* GitHub mirror: <https://github.com/cran/cSEM>\n\nRun `revdepcheck::revdep_details(, \"cSEM\")` for more info\n\n## In both\n\n*   checking dependencies in R code ... NOTE\n     ```\n     Namespace in Imports field not imported from: ‘Rdpack’\n       All declared Imports should be used.\n     ```\n\n# ctsem (3.10.6)\n\n* GitHub: <https://github.com/cdriveraus/ctsem>\n* Email: <mailto:charles.driver2@uzh.ch>\n* GitHub mirror: <https://github.com/cran/ctsem>\n\nRun `revdepcheck::revdep_details(, \"ctsem\")` for more info\n\n## In both\n\n*   checking whether package ‘ctsem’ can be installed ... WARNING\n     ```\n     Found the following significant warnings:\n       Warning: namespace ‘colorspace’ is not available and has been replaced\n     See ‘/scratch/henrik/revdep/future.apply/checks/ctsem/new/ctsem.Rcheck/00install.out’ for details.\n     ```\n\n*   checking re-building of vignette outputs ... WARNING\n     ```\n     ...\n       ...\n     --- re-building ‘hierarchicalmanual.rnw’ using knitr_notangle\n     Warning in texi2dvi(file = file, pdf = TRUE, clean = clean, quiet = quiet,  :\n       texi2dvi script/program not available, using emulation\n     Error: processing vignette 'hierarchicalmanual.rnw' failed with diagnostics:\n     unable to run pdflatex on 'hierarchicalmanual.tex'\n     LaTeX errors:\n     ! LaTeX Error: File `apacite.sty' not found.\n     \n     Type X to quit or <RETURN> to proceed,\n     or enter new name. (Default extension: sty)\n     \n     ! Emergency stop.\n     <read *> \n              \n     l.62 \\bibliographystyle\n                            {apacite}     % Set bibliography style^^M\n     !  ==> Fatal error occurred, no output PDF file produced!\n     --- failed re-building ‘hierarchicalmanual.rnw’\n     \n     SUMMARY: processing the following file failed:\n       ‘hierarchicalmanual.rnw’\n     \n     Error: Vignette re-building failed.\n     Execution halted\n     ```\n\n# disk.frame (0.8.3)\n\n* GitHub: <https://github.com/DiskFrame/disk.frame>\n* Email: <mailto:zhuojia.dai@gmail.com>\n* GitHub mirror: <https://github.com/cran/disk.frame>\n\nRun `revdepcheck::revdep_details(, \"disk.frame\")` for more info\n\n## In both\n\n*   checking Rd files ... NOTE\n     ```\n     checkRd: (-1) csv_to_disk.frame.Rd:56: Lost braces; missing escapes or markup?\n         56 | strings, and you are encouraged to use {fasttime} to convert the strings to\n            |                                        ^\n     checkRd: (-1) purrr_as_mapper.Rd:10: Lost braces; missing escapes or markup?\n         10 | \\item{.f}{a normal function or purrr syntax function i.e. `~{ ...code...}`}\n            |                                                             ^\n     ```\n\n# EFAtools (0.6.1)\n\n* GitHub: <https://github.com/mdsteiner/EFAtools>\n* Email: <mailto:markus.d.steiner@gmail.com>\n* GitHub mirror: <https://github.com/cran/EFAtools>\n\nRun `revdepcheck::revdep_details(, \"EFAtools\")` for more info\n\n## In both\n\n*   checking dependencies in R code ... NOTE\n     ```\n     Namespace in Imports field not imported from: ‘progress’\n       All declared Imports should be used.\n     ```\n\n# fabletools (0.6.1)\n\n* GitHub: <https://github.com/tidyverts/fabletools>\n* Email: <mailto:mail@mitchelloharawild.com>\n* GitHub mirror: <https://github.com/cran/fabletools>\n\nRun `revdepcheck::revdep_details(, \"fabletools\")` for more info\n\n## In both\n\n*   checking examples ... ERROR\n     ```\n     ...\n      2 Adelaide       South Australia    Holiday  157.   27.1 \n      3 Adelaide       South Australia    Other     56.6  17.3 \n      4 Adelaide       South Australia    Visiting 205.   32.5 \n      5 Adelaide Hills South Australia    Business   2.66  4.30\n      6 Adelaide Hills South Australia    Holiday   10.5   6.37\n      7 Adelaide Hills South Australia    Other      1.40  1.65\n      8 Adelaide Hills South Australia    Visiting  14.2  10.7 \n      9 Alice Springs  Northern Territory Business  14.6   7.20\n     10 Alice Springs  Northern Territory Holiday   31.9  18.1 \n     # ℹ 294 more rows\n     > \n     > # Search and use useful features with `feature_set()`. \n     > \n     > ## Don't show: \n     > if (requireNamespace(\"feasts\", quietly = TRUE)) withAutoprint({ # examplesIf\n     + ## End(Don't show)\n     + library(feasts)\n     + ## Don't show: \n     + }) # examplesIf\n     > ## End(Don't show)\n     > tourism %>% \n     +   features(Trips, features = feature_set(tags = \"autocorrelation\"))\n     Error in .l[[1]] : subscript out of bounds\n     Calls: %>% ... features.tbl_ts -> features_impl -> map -> lapply -> FUN -> transpose\n     Execution halted\n     ```\n\n# FracFixR (1.0.0)\n\n* Email: <mailto:alice.cleynen@cnrs.fr>\n* GitHub mirror: <https://github.com/cran/FracFixR>\n\nRun `revdepcheck::revdep_details(, \"FracFixR\")` for more info\n\n## In both\n\n*   checking re-building of vignette outputs ... ERROR\n     ```\n     ...\n          ▆\n       1. ├─FracFixR::FracFixR(MatrixCounts = counts, Annotation = annotation)\n       2. │ └─future::plan(...)\n       3. │   └─future (local) plan_set(...)\n       4. │     └─future:::plan_init(stack[[1]], debug = debug)\n       5. │       └─future:::makeFutureBackend(evaluator, debug = debug)\n       6. │         └─base::do.call(factory, args = args, envir = envir)\n       7. └─future (local) `<fn>`(workers = 255)\n       8.   └─future::ClusterFutureBackend(...)\n       9.     └─clusterRegistry$startCluster(...)\n      10.       └─future (local) makeCluster(workers, ...)\n      11.         ├─base::do.call(makeClusterPSOCK, args = args, quote = TRUE)\n      12.         └─parallelly (local) `<fn>`(base::quote(255L), rscript_libs = base::quote(`<chr>`))\n      13.           └─parallelly:::checkNumberOfLocalWorkers(workers)\n     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n     \n     Error: processing vignette 'FracFixR-intro.Rmd' failed with diagnostics:\n     Attempting to set up 255 localhost parallel workers with only 5 CPU cores available for this R process (per 'N/A'), which could result in a 5100% load. The hard limit is set to 300%. Overusing the CPUs has negative impact on the current R process, but also on all other processes of yours and others running on the same machine. See help(\"parallelly.maxWorkers.localhost\", package = \"parallelly\") for further explanations and how to override the hard limit that triggered this error. By the way, was parallel::detectCores() used, because the number of workers (255) equals detectCores() - 1? If so, please use parallelly::availableCores() instead\n     --- failed re-building ‘FracFixR-intro.Rmd’\n     \n     SUMMARY: processing the following file failed:\n       ‘FracFixR-intro.Rmd’\n     \n     Error: Vignette re-building failed.\n     Execution halted\n     ```\n\n# hero (0.6)\n\n* Email: <mailto:joshua.french@ucdenver.edu>\n* GitHub mirror: <https://github.com/cran/hero>\n\nRun `revdepcheck::revdep_details(, \"hero\")` for more info\n\n## In both\n\n*   checking Rd files ... NOTE\n     ```\n     checkRd: (-1) hero.Rd:67-68: Lost braces\n         67 | then \\code{\\link[pbapply]{pblapply}} is used. If code{package ==\n            |                                                      ^\n     checkRd: (-1) hero.Rd:69: Lost braces\n         69 | code{package == \"Rmpi\"}, then \\code{\\link[Rmpi]{mpi.applyLB}} is used.}\n            |     ^\n     ```\n\n# InPAS (2.18.1)\n\n* Email: <mailto:jou@morgridge.org>\n\nRun `revdepcheck::revdep_details(, \"InPAS\")` for more info\n\n## In both\n\n*   checking dependencies in R code ... NOTE\n     ```\n     There are ::: calls to the package's namespace in its code. A package\n       almost never needs to use ::: for its own objects:\n       ‘adjust_distalCPs’ ‘adjust_proximalCPs’ ‘adjust_proximalCPsByNBC’\n       ‘adjust_proximalCPsByPWM’ ‘calculate_mse’ ‘find_valleyBySpline’\n       ‘get_PAscore’ ‘get_PAscore2’ ‘remove_convergentUTR3s’\n       ‘search_distalCPs’ ‘search_proximalCPs’\n     ```\n\n*   checking Rd metadata ... NOTE\n     ```\n     Invalid package aliases in Rd file 'InPAS.Rd':\n       ‘-package’\n     ```\n\n*   checking Rd \\usage sections ... NOTE\n     ```\n     Documented arguments not in \\usage in Rd file 'get_UTR3TotalCov.Rd':\n       ‘gcCompensationensation’\n     \n     Functions with \\usage entries need to have the appropriate \\alias\n     entries, and all their arguments documented.\n     The \\usage entries must correspond to syntactically valid R code.\n     See chapter ‘Writing R documentation files’ in the ‘Writing R\n     Extensions’ manual.\n     ```\n\n# ivmte (1.4.0)\n\n* Email: <mailto:jkcshea@uchicago.edu>\n* GitHub mirror: <https://github.com/cran/ivmte>\n\nRun `revdepcheck::revdep_details(, \"ivmte\")` for more info\n\n## In both\n\n*   checking Rd files ... NOTE\n     ```\n     checkRd: (-1) sTsls.Rd:17: Lost braces; missing escapes or markup?\n         17 | \\item{pi}{the matrix E[XZ']E[ZZ']^{-1}}\n            |                                   ^\n     checkRd: (-1) sTslsSplines.Rd:20: Lost braces; missing escapes or markup?\n         20 | \\item{pi}{matrix, corresponds to E[XZ']E[ZZ']^{-1}, the first stage\n            |                                               ^\n     ```\n\n# kappaGold (0.4.0)\n\n* Email: <mailto:matthias.kuhn@tu-dresden.de>\n* GitHub mirror: <https://github.com/cran/kappaGold>\n\nRun `revdepcheck::revdep_details(, \"kappaGold\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n       Missing dependency on R >= 4.1.0 because package code uses the pipe\n       |> or function shorthand \\(...) syntax added in R 4.1.0.\n       File(s) using such syntax:\n         ‘kappa_inference.R’\n     ```\n\n# lavDiag (0.1.0)\n\n* GitHub: <https://github.com/reckak/lavDiag>\n* Email: <mailto:reckak@mail.muni.cz>\n* GitHub mirror: <https://github.com/cran/lavDiag>\n\nRun `revdepcheck::revdep_details(, \"lavDiag\")` for more info\n\n## In both\n\n*   checking tests ...\n     ```\n     ...\n         6. │     └─furrr:::furrr_template(...)\n         7. │       ├─future::nbrOfWorkers()\n         8. │       └─future:::nbrOfWorkers.NULL()\n         9. │         └─future::plan(\"backend\")\n        10. │           └─future:::plan_init(strategy, debug = debug)\n        11. │             └─future:::makeFutureBackend(evaluator, debug = debug)\n        12. │               └─base::do.call(factory, args = args, envir = envir)\n        13. └─future (local) `<fn>`(workers = 255L)\n        14.   └─future::ClusterFutureBackend(...)\n        15.     └─clusterRegistry$startCluster(...)\n        16.       └─future (local) makeCluster(workers, ...)\n        17.         ├─base::do.call(makeClusterPSOCK, args = args, quote = TRUE)\n        18.         └─parallelly (local) `<fn>`(base::quote(255L), rscript_libs = base::quote(`<chr>`))\n        19.           └─parallelly:::checkNumberOfLocalWorkers(workers)\n       ── Error ('test-prepare.R:12:3'): prepare merges branches for mixed model ──────\n       Error in `prepare(fit, length.out = 15)`: Neither continuous nor ordinal branch succeeded - check model/functions.\n       Backtrace:\n           ▆\n        1. └─lavDiag::prepare(fit, length.out = 15) at test-prepare.R:12:3\n        2.   └─rlang::abort(\"Neither continuous nor ordinal branch succeeded - check model/functions.\")\n       \n       [ FAIL 3 | WARN 25 | SKIP 1 | PASS 28 ]\n       Error:\n       ! Test failures.\n       Execution halted\n     ```\n\n# MAI (1.16.0)\n\n* GitHub: <https://github.com/KechrisLab/MAI>\n* Email: <mailto:Jonathan.Dekermanjian@CUAnschutz.edu>\n\nRun `revdepcheck::revdep_details(, \"MAI\")` for more info\n\n## In both\n\n*   checking top-level files ... NOTE\n     ```\n     File\n       LICENSE\n     is not mentioned in the DESCRIPTION file.\n     ```\n\n# mikropml (1.7.0)\n\n* GitHub: <https://github.com/SchlossLab/mikropml>\n* Email: <mailto:sovacool@umich.edu>\n* GitHub mirror: <https://github.com/cran/mikropml>\n\nRun `revdepcheck::revdep_details(, \"mikropml\")` for more info\n\n## In both\n\n*   checking dependencies in R code ... NOTE\n     ```\n     Namespace in Imports field not imported from: ‘methods’\n       All declared Imports should be used.\n     ```\n\n# nixtlar (0.6.2)\n\n* GitHub: <https://github.com/Nixtla/nixtlar>\n* Email: <mailto:mariana@nixtla.io>\n* GitHub mirror: <https://github.com/cran/nixtlar>\n\nRun `revdepcheck::revdep_details(, \"nixtlar\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n       Missing dependency on R >= 4.1.0 because package code uses the pipe\n       |> or function shorthand \\(...) syntax added in R 4.1.0.\n       File(s) using such syntax:\n         ‘get_model_params.R’ ‘level_from_quantiles.R’ ‘make_request.R’\n         ‘nixtla_client_cross_validation.R’ ‘nixtla_client_detect_anomalies.R’\n         ‘nixtla_client_forecast.R’ ‘nixtla_client_historic.R’\n         ‘nixtla_client_plot.R’ ‘nixtla_validate_api_key.R’\n         ‘validate_exogenous.R’\n     ```\n\n# OutSeekR (1.1.0)\n\n* Email: <mailto:pboutros@sbpdiscovery.org>\n* GitHub mirror: <https://github.com/cran/OutSeekR>\n\nRun `revdepcheck::revdep_details(, \"OutSeekR\")` for more info\n\n## In both\n\n*   checking dependencies in R code ... NOTE\n     ```\n     Namespaces in Imports field not imported from:\n       ‘future’ ‘truncnorm’\n       All declared Imports should be used.\n     ```\n\n# PAMpal (1.4.4)\n\n* Email: <mailto:taiki.sakai@noaa.gov>\n* GitHub mirror: <https://github.com/cran/PAMpal>\n\nRun `revdepcheck::revdep_details(, \"PAMpal\")` for more info\n\n## In both\n\n*   checking whether package ‘PAMpal’ can be installed ... WARNING\n     ```\n     Found the following significant warnings:\n       Warning: no DISPLAY variable so Tk is not available\n     See ‘/scratch/henrik/revdep/future.apply/checks/PAMpal/new/PAMpal.Rcheck/00install.out’ for details.\n     ```\n\n# PAMscapes (0.15.0)\n\n* Email: <mailto:taiki.sakai@noaa.gov>\n* GitHub mirror: <https://github.com/cran/PAMscapes>\n\nRun `revdepcheck::revdep_details(, \"PAMscapes\")` for more info\n\n## In both\n\n*   checking whether package ‘PAMscapes’ can be installed ... WARNING\n     ```\n     Found the following significant warnings:\n       Warning: no DISPLAY variable so Tk is not available\n     See ‘/scratch/henrik/revdep/future.apply/checks/PAMscapes/new/PAMscapes.Rcheck/00install.out’ for details.\n     ```\n\n# pavo (2.9.0)\n\n* GitHub: <https://github.com/rmaia/pavo>\n* Email: <mailto:thomas.white026@gmail.com>\n* GitHub mirror: <https://github.com/cran/pavo>\n\nRun `revdepcheck::revdep_details(, \"pavo\")` for more info\n\n## In both\n\n*   checking whether package ‘pavo’ can be installed ... WARNING\n     ```\n     Found the following significant warnings:\n       Warning: no DISPLAY variable so Tk is not available\n     See ‘/scratch/henrik/revdep/future.apply/checks/pavo/new/pavo.Rcheck/00install.out’ for details.\n     ```\n\n# pgxRpi (1.6.0)\n\n* GitHub: <https://github.com/progenetix/pgxRpi>\n* Email: <mailto:hangjia.zhao@uzh.ch>\n\nRun `revdepcheck::revdep_details(, \"pgxRpi\")` for more info\n\n## In both\n\n*   checking R code for possible problems ... NOTE\n     ```\n     pgxSegprocess: no visible binding for global variable\n       ‘followup_state_id’\n     Undefined global functions or variables:\n       followup_state_id\n     ```\n\n# powRICLPM (0.2.1)\n\n* GitHub: <https://github.com/JeroenDMulder/powRICLPM>\n* Email: <mailto:j.d.mulder@uu.nl>\n* GitHub mirror: <https://github.com/cran/powRICLPM>\n\nRun `revdepcheck::revdep_details(, \"powRICLPM\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n       Missing dependency on R >= 4.1.0 because package code uses the pipe\n       |> or function shorthand \\(...) syntax added in R 4.1.0.\n       File(s) using such syntax:\n         ‘save.R’\n     ```\n\n# qape (2.1)\n\n* Email: <mailto:alicja.wolny-dominiak@ue.katowice.pl>\n* GitHub mirror: <https://github.com/cran/qape>\n\nRun `revdepcheck::revdep_details(, \"qape\")` for more info\n\n## In both\n\n*   checking Rd files ... NOTE\n     ```\n     checkRd: (-1) srswrRe.Rd:10: Lost braces\n         10 |   \\item{listRanef}{{\\emph{ranef(model)}} object where {\\emph{model}} is an { \\emph{lmer}} object.}\n            |                                                                            ^\n     ```\n\n# QDNAseq (1.46.0)\n\n* GitHub: <https://github.com/ccagc/QDNAseq>\n* Email: <mailto:d.sie@vumc.nl>\n\nRun `revdepcheck::revdep_details(, \"QDNAseq\")` for more info\n\n## In both\n\n*   checking re-building of vignette outputs ... WARNING\n     ```\n     ...\n     Total time:0minutes\n     \n     Warning in texi2dvi(file = file, pdf = TRUE, clean = clean, quiet = quiet,  :\n       texi2dvi script/program not available, using emulation\n     Error: processing vignette 'QDNAseq.Rnw' failed with diagnostics:\n     unable to run pdflatex on 'QDNAseq.tex'\n     LaTeX errors:\n     ! LaTeX Error: File `nowidow.sty' not found.\n     \n     Type X to quit or <RETURN> to proceed,\n     or enter new name. (Default extension: sty)\n     \n     ! Emergency stop.\n     <read *> \n              \n     l.197 \\RequirePackage\n                          {parnotes}^^M\n     !  ==> Fatal error occurred, no output PDF file produced!\n     --- failed re-building ‘QDNAseq.Rnw’\n     \n     SUMMARY: processing the following file failed:\n       ‘QDNAseq.Rnw’\n     \n     Error: Vignette re-building failed.\n     Execution halted\n     ```\n\n# receptiviti (0.2.1)\n\n* GitHub: <https://github.com/Receptiviti/receptiviti-r>\n* Email: <mailto:kenglish@receptiviti.com>\n* GitHub mirror: <https://github.com/cran/receptiviti>\n\nRun `revdepcheck::revdep_details(, \"receptiviti\")` for more info\n\n## In both\n\n*   checking tests ...\n     ```\n     ...\n       \n       ══ Skipped tests (4) ═══════════════════════════════════════════════════════════\n       • no API key (4): 'test-receptiviti.R:78:1',\n         'test-receptiviti_frameworks.R:1:1', 'test-receptiviti_norming.R:12:1',\n         'test-receptiviti_status.R:13:1'\n       \n       ══ Failed tests ════════════════════════════════════════════════════════════════\n       ── Error ('test-receptiviti.R:9:3'): invalid inputs are caught ─────────────────\n       Error: Invalid header received from client.\n       \n       Backtrace:\n           ▆\n        1. ├─testthat::expect_error(...) at test-receptiviti.R:9:3\n        2. │ └─testthat:::expect_condition_matching_(...)\n        3. │   └─testthat:::quasi_capture(...)\n        4. │     ├─testthat (local) .capture(...)\n        5. │     │ └─base::withCallingHandlers(...)\n        6. │     └─rlang::eval_bare(quo_get_expr(.quo), quo_get_env(.quo))\n        7. └─receptiviti::receptiviti(...)\n        8.   └─receptiviti:::manage_request(...)\n       \n       [ FAIL 1 | WARN 0 | SKIP 4 | PASS 5 ]\n       Error:\n       ! Test failures.\n       Execution halted\n     ```\n\n# rsi (0.3.2)\n\n* GitHub: <https://github.com/Permian-Global-Research/rsi>\n* Email: <mailto:mike.mahoney.218@gmail.com>\n* GitHub mirror: <https://github.com/cran/rsi>\n\nRun `revdepcheck::revdep_details(, \"rsi\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n       Missing dependency on R >= 4.1.0 because package code uses the pipe\n       |> or function shorthand \\(...) syntax added in R 4.1.0.\n       File(s) using such syntax:\n         ‘calculate_indices.Rd’ ‘get_stac_data.R’ ‘get_stac_data.Rd’\n         ‘landsat_mask_function.Rd’\n     ```\n\n# signeR (2.12.0)\n\n* GitHub: <https://github.com/TojalLab/signeR>\n* Email: <mailto:renan.valieris@accamargo.org.br>\n\nRun `revdepcheck::revdep_details(, \"signeR\")` for more info\n\n## In both\n\n*   checking C++ specification ... NOTE\n     ```\n       Specified C++14: please drop specification unless essential\n     ```\n\n*   checking R code for possible problems ... NOTE\n     ```\n     ...\n       ‘Samples’\n     ExposureClassify,ANY-character: no visible binding for global variable\n       ‘Col’\n     ExposureClassify,ANY-character: no visible binding for global variable\n       ‘Frequency’\n     ExposureClassify,ANY-character: no visible binding for global variable\n       ‘Row’\n     ExposureClassifyCV,ANY-character: no visible binding for global\n       variable ‘Col’\n     ExposureClassifyCV,ANY-character: no visible binding for global\n       variable ‘Frequency’\n     ExposureClassifyCV,ANY-character: no visible binding for global\n       variable ‘Row’\n     ExposureCorrelation,SignExp-numeric: no visible binding for global\n       variable ‘Feature’\n     ExposureCorrelation,SignExp-numeric: no visible binding for global\n       variable ‘exposure’\n     ExposureCorrelation,matrix-numeric: no visible binding for global\n       variable ‘Feature’\n     ExposureCorrelation,matrix-numeric: no visible binding for global\n       variable ‘exposure’\n     Undefined global functions or variables:\n       . Col Feature Frequency Reference_Allele Row Samples Signatures\n       Tumor_Seq_Allele1 Tumor_Seq_Allele2 Variant_Type conf.high conf.low\n       estimate exposure fc p.value project sig sig_test term\n     ```\n\n*   checking Rd files ... NOTE\n     ```\n     prepare_Rd: cosmic_data.Rd:91-93: Dropping empty section \\details\n     prepare_Rd: cosmic_data.Rd:98-100: Dropping empty section \\references\n     prepare_Rd: cosmic_data.Rd:101-102: Dropping empty section \\examples\n     prepare_Rd: tcga_similarities.Rd:96-98: Dropping empty section \\details\n     prepare_Rd: tcga_similarities.Rd:99-101: Dropping empty section \\source\n     prepare_Rd: tcga_similarities.Rd:102-104: Dropping empty section \\references\n     prepare_Rd: tcga_similarities.Rd:105-106: Dropping empty section \\examples\n     prepare_Rd: tcga_tumors.Rd:18-20: Dropping empty section \\details\n     prepare_Rd: tcga_tumors.Rd:21-23: Dropping empty section \\source\n     prepare_Rd: tcga_tumors.Rd:24-26: Dropping empty section \\references\n     prepare_Rd: tcga_tumors.Rd:27-28: Dropping empty section \\examples\n     ```\n\n# solitude (1.1.3)\n\n* GitHub: <https://github.com/talegari/solitude>\n* Email: <mailto:sri.teach@gmail.com>\n* GitHub mirror: <https://github.com/cran/solitude>\n\nRun `revdepcheck::revdep_details(, \"solitude\")` for more info\n\n## In both\n\n*   checking dependencies in R code ... NOTE\n     ```\n     Namespaces in Imports field not imported from:\n       ‘R6’ ‘lgr’\n       All declared Imports should be used.\n     ```\n\n# sperrorest (3.0.5)\n\n* GitHub: <https://github.com/giscience-fsu/sperrorest>\n* Email: <mailto:alexander.brenning@uni-jena.de>\n* GitHub mirror: <https://github.com/cran/sperrorest>\n\nRun `revdepcheck::revdep_details(, \"sperrorest\")` for more info\n\n## In both\n\n*   checking Rd files ... NOTE\n     ```\n     ...\n            |                                          ^\n     checkRd: (-1) partition_kmeans.Rd:41: Lost braces; missing escapes or markup?\n         41 | if \\code{TRUE} (used internally by other {sperrorest} functions), return a\n            |                                          ^\n     checkRd: (-1) partition_tiles.Rd:78: Lost braces; missing escapes or markup?\n         78 | if \\code{TRUE} (used internally by other {sperrorest} functions), return a\n            |                                          ^\n     checkRd: (-1) sperrorest.Rd:55: Lost braces; missing escapes or markup?\n         55 | \\code{formula} and \\code{data} argument, which are provided by {sperrorest})}\n            |                                                                ^\n     checkRd: (-1) sperrorest.Rd:63: Lost braces; missing escapes or markup?\n         63 | {sperrorest}).}\n            | ^\n     checkRd: (-1) sperrorest.Rd:135: Lost braces; missing escapes or markup?\n        135 | A list (object of class {sperrorest}) with (up to) six components:\n            |                         ^\n     checkRd: (-1) sperrorest.Rd:148: Lost braces; missing escapes or markup?\n        148 | information about the {sperrorest} package version\n            |                       ^\n     checkRd: (-1) summary.sperroresterror.Rd:5: Lost braces; missing escapes or markup?\n          5 | \\title{Summarize error statistics obtained by {sperrorest}}\n            |                                               ^\n     checkRd: (-1) summary.sperrorestimportance.Rd:5: Lost braces; missing escapes or markup?\n          5 | \\title{Summarize variable importance statistics obtained by {sperrorest}}\n            |                                                             ^\n     ```\n\n# stppSim (1.3.4)\n\n* GitHub: <https://github.com/Manalytics/stppSim>\n* Email: <mailto:monsuur2010@yahoo.com>\n* GitHub mirror: <https://github.com/cran/stppSim>\n\nRun `revdepcheck::revdep_details(, \"stppSim\")` for more info\n\n## In both\n\n*   checking whether package ‘stppSim’ can be installed ... WARNING\n     ```\n     Found the following significant warnings:\n       Warning: no DISPLAY variable so Tk is not available\n     See ‘/scratch/henrik/revdep/future.apply/checks/stppSim/new/stppSim.Rcheck/00install.out’ for details.\n     ```\n\n# tramvs (0.0-8)\n\n* Email: <mailto:lucasheinrich.kook@gmail.com>\n* GitHub mirror: <https://github.com/cran/tramvs>\n\nRun `revdepcheck::revdep_details(, \"tramvs\")` for more info\n\n## In both\n\n*   checking re-building of vignette outputs ... WARNING\n     ```\n     ...\n       ...\n     --- re-building ‘tramvs.Rnw’ using knitr\n     Warning in texi2dvi(file = file, pdf = TRUE, clean = clean, quiet = quiet,  :\n       texi2dvi script/program not available, using emulation\n     Error: processing vignette 'tramvs.Rnw' failed with diagnostics:\n     unable to run pdflatex on 'tramvs.tex'\n     LaTeX errors:\n     ! LaTeX Error: File `wrapfig.sty' not found.\n     \n     Type X to quit or <RETURN> to proceed,\n     or enter new name. (Default extension: sty)\n     \n     ! Emergency stop.\n     <read *> \n              \n     l.68 \\usepackage\n                     {float}^^M\n     !  ==> Fatal error occurred, no output PDF file produced!\n     --- failed re-building ‘tramvs.Rnw’\n     \n     SUMMARY: processing the following file failed:\n       ‘tramvs.Rnw’\n     \n     Error: Vignette re-building failed.\n     Execution halted\n     ```\n\n# tsgarch (1.0.3)\n\n* GitHub: <https://github.com/tsmodels/tsgarch>\n* Email: <mailto:alexios@4dscape.com>\n* GitHub mirror: <https://github.com/cran/tsgarch>\n\nRun `revdepcheck::revdep_details(, \"tsgarch\")` for more info\n\n## In both\n\n*   checking DESCRIPTION meta-information ... NOTE\n     ```\n       Missing dependency on R >= 4.1.0 because package code uses the pipe\n       |> or function shorthand \\(...) syntax added in R 4.1.0.\n       File(s) using such syntax:\n         ‘benchmark.R’ ‘print.R’\n     ```\n\n# txshift (0.3.8)\n\n* GitHub: <https://github.com/nhejazi/txshift>\n* Email: <mailto:nh@nimahejazi.org>\n* GitHub mirror: <https://github.com/cran/txshift>\n\nRun `revdepcheck::revdep_details(, \"txshift\")` for more info\n\n## In both\n\n*   checking Rd files ... NOTE\n     ```\n     checkRd: (-1) est_g_exp.Rd:55: Lost braces; missing escapes or markup?\n         55 |  {A - delta}, {A + delta}, and {A + 2 * delta}).\n            |  ^\n     checkRd: (-1) est_g_exp.Rd:55: Lost braces; missing escapes or markup?\n         55 |  {A - delta}, {A + delta}, and {A + 2 * delta}).\n            |               ^\n     checkRd: (-1) est_g_exp.Rd:55: Lost braces; missing escapes or markup?\n         55 |  {A - delta}, {A + delta}, and {A + 2 * delta}).\n            |                                ^\n     ```\n\n"
  },
  {
    "path": "revdep/revdepcheck.Renviron",
    "content": "## Environment variables set by revdepcheck.extras::run()\nR_REVDEPCHECK_TIMEOUT=${R_REVDEPCHECK_TIMEOUT:-180}\nTAR_SKIP_CLUSTERMQ=${TAR_SKIP_CLUSTERMQ-true}\n\n## Allow for at least two workers\nR_PARALLELLY_AVAILABLECORES_FALLBACK=2\n\n## Allow for at most 5 cores\n## Needed for parallelly (< 1.46.0), which will return\n## detectCores() when check vignettes\nR_PARALLELLY_AVAILABLECORES_MAX=5\n\n## Allow for at most 8 threads\nOMP_NUM_THREADS=8\nOPENBLAS_NUM_THREADS=8\nMKL_NUM_THREADS=8\nGOTO_NUM_THREADS=8\n\n## Turn on more checks\n#NOT_CRAN=true\n\nR_FUTURE_PLAN_EARLYSIGNAL=defunct\nR_FUTURE_FUTURE_EARLYSIGNAL=defunct\nR_FUTURE_FUTURE_LOCAL=defunct\nR_FUTURE_FUTURE_GC=defunct\nR_FUTURE_RESOLVED_RUN=defunct\n"
  },
  {
    "path": "revdep/revdepcheck.init.sh",
    "content": "#! /usr/bin/env bash\n\n## Missing or outdated LaTeX packages\nif (FALSE) {\n  tinytex::install_tinytex(force = TRUE)\n  message(\"TeX root: \", tinytex::tinytex_root())\n  tinytex::tlmgr_update()\n  tinytex::tlmgr_install(\"nowidow\")  # QDNAseq\n  tinytex::tlmgr_install(\"wrapfig\")  # tramvs\n  tinytex::tlmgr_install(\"apacite\")  # ctsem\n}\n\n## Add packages to check\nrevdep/run.R --add-children\n\n## Drop packages no longer on CRAN (2026-02-19)\nrevdep/run.R --rm forecastML\n\n## Drop packages failing on Bioconductor (2026-02-19)\nrevdep/run.R --rm MineICA\n\n## Too many cores because of detectCores()\n# NSLOTS=4 revdep/run.R --add FracFixR lavDiag\n"
  },
  {
    "path": "revdep/run.R",
    "content": "#!/usr/bin/env Rscript\n\nprecheck <- function() {\n  ## WORKAROUND: Remove checked pkgs that use file links, which otherwise\n  ## produce warnings which are promoted to errors by revdepcheck.\n  unlink(\"revdep/checks/aroma.affymetrix\", recursive = TRUE)\n}\n\nrevdepcheck.extras::run()\n"
  },
  {
    "path": "revdep/run.pbs",
    "content": "#!/bin/bash\n## Example: qsub -l nodes=1:ppn=24 -l vmem=30gb revdep/run.pbs\n#PBS -j oe  # Join STDERR and STDOUT\ncd \"$PBS_O_WORKDIR\"\n\nmodule load r\nRscript revdep/run.R\n"
  },
  {
    "path": "revdep/run.sge",
    "content": "#!/bin/bash\n## Example: qsub -pe smp 24 -l h_rt=08:00:00 revdep/run.sge\n#$ -S /bin/bash\n#$ -R yes         # SGE host reservation, highly recommended\n#$ -cwd           # Current working directory\n#$ -j y           # Join STDERR and STDOUT\n#$ -l mem_free=3G # On average 4 GiB of RAM per core (=a package check)\n#$ -m bea         # email when job (b)egins, (e)nds, or (a)borts\n#\n# Pass on R-specific environment variables, iff set:\n##$ -v _R_CHECK_LENGTH_1_CONDITION_\n##$ -v _R_CHECK_LENGTH_1_LOGIC2_\n##$ -v R_STARTUP_DEBUG\n\n## SPECIAL: On Wynton HPC\nif [[ $SGE_CLUSTER_NAME == *wynton* ]]; then\n    module load CBI\n    module load r\n\n    ## Some packages need a more modern version of gcc, e.g. 'balvaan'\n    module load scl-devtoolset/4\n\n    ## Some packages require non-default system libraries\n    module load gdal geos gsl hdf5 jags\n\n    ## Install all packages to toward $TMPDIR, if revdep/library doesn't already exist.\n    ## This will avoid some of the slowness on the global file system\n    #if [[ ! -d revdep/library ]]; then\n    #    tmpdir=$(mktemp -d)\n    #    ln -fs \"$tmpdir\" revdep/library\n    #    [[ -d revdep/library ]] || { >&2 echo \"ERROR: Failed to link revdep/library/ to $tmpdir\"; exit 1; }\n    #fi\n\n    ## To check in on revdep/library/ on the running host (see below), submit a job like:\n    ##   echo \"ls -lR revdep/library/\" | qsub -cwd -j yes -l hostname=<hostname>\n    \n    ## Assert that revdep/library is on $TMPDIR\n    #if [[ ! \"$(readlink revdep/library)\" = $TMPDIR* ]]; then\n    #    >&2 echo \"ERROR: revdep/library/ already exists but is not on $TMPDIR\"\n    #    exit 1\n    #fi\nfi\n\necho \"HOSTNAME: $HOSTNAME\"\nls -l revdep/\n\nRscript --version\nRscript -e \".libPaths()\"\nRscript revdep/run.R\n"
  },
  {
    "path": "tests/incl/end.R",
    "content": "## Undo future strategy\nfuture::plan(oplan)\n\n\n## Undo options\n## (a) Added\nadded <- setdiff(names(options()), names(oopts0))\nopts <- vector(\"list\", length = length(added))\nnames(opts) <- added\noptions(opts)\n## (b) Modified\noptions(oopts)\n## (c) Assert that everything was undone\nstopifnot(all.equal(options(), oopts0))\n\n\n## Undo system environment variables\n## (a) Added\ncenvs <- Sys.getenv()\nadded <- setdiff(names(cenvs), names(oenvs0))\nfor (name in added) Sys.unsetenv(name)\n## (b) Missing\nmissing <- setdiff(names(oenvs0), names(cenvs))\nif (length(missing) > 0) {\n  values <- oenvs0[missing]\n  do.call(Sys.setenv, as.list(values))\n  ## WORKAROUND: Most platforms allow setting an environment variable to\n  ## \"\", but Windows does not and there Sys.setenv(FOO = \"\") unsets FOO.\n  if (.Platform$OS.type == \"windows\") {\n    drop <- missing[!nzchar(values)]\n    if (length(drop) > 0) {\n      oenvs0 <- oenvs0[setdiff(names(oenvs0), drop)]\n      ## In case Sys.setenv() supports empty string in the future\n      Sys.unsetenv(drop)\n    }\n  }\n}\n## (c) Modified?\nfor (name in intersect(names(cenvs), names(oenvs0))) {\n  ## WORKAROUND: On Linux Wine, base::Sys.getenv() may\n  ## return elements with empty names. /HB 2016-10-06\n  if (nchar(name) == 0) next\n  if (!identical(cenvs[[name]], oenvs0[[name]])) {\n    do.call(Sys.setenv, as.list(oenvs0[name]))\n    ## WORKAROUND: Most platforms allow setting an environment variable to\n    ## \"\", but Windows does not and there Sys.setenv(FOO = \"\") unsets FOO.\n    if (.Platform$OS.type == \"windows\" && !nzchar(oenvs0[[name]])) {\n      oenvs0 <- oenvs0[setdiff(names(oenvs0), name)]\n      ## In case Sys.setenv() supports empty string in the future\n      Sys.unsetenv(name)\n    }\n  }\n}\n## (d) Assert that everything was undone\nstopifnot(identical(Sys.getenv(), oenvs0))\n\n\n## Undo variables\nrm(list = c(setdiff(ls(), ovars)))\n\n\n## Travis CI specific: Explicit garbage collection because it\n## looks like Travis CI might run out of memory during 'covr'\n## testing and we now have so many tests. /HB 2017-01-11\nif (\"covr\" %in% loadedNamespaces()) gc()\n"
  },
  {
    "path": "tests/incl/start,load-only.R",
    "content": "## Record original state\novars <- ls()\noenvs <- oenvs0 <- Sys.getenv()\noopts0 <- options()\n\ncovr_testing <- (\"covr\" %in% loadedNamespaces())\non_solaris <- grepl(\"^solaris\", R.version$os)\n\n## Default options\noopts <- options(\n  warn = 1L,\n  mc.cores = 2L,\n  future.debug = TRUE,\n  ## Reset the following during testing in case\n  ## they are set on the test system\n  future.availableCores.system = NULL,\n  future.availableCores.fallback = NULL\n)\n\n\n## Reset the following during testing in case\n## they are set on the test system\noenvs2 <- Sys.unsetenv(c(\n  \"R_FUTURE_AVAILABLECORES_SYSTEM\",\n  \"R_FUTURE_AVAILABLECORES_FALLBACK\",\n  ## SGE\n  \"NSLOTS\", \"PE_HOSTFILE\",\n  ## Slurm\n  \"SLURM_CPUS_PER_TASK\",\n  ## TORQUE / PBS\n  \"PBS_NUM_PPN\", \"PBS_NODEFILE\", \"PBS_NP\", \"PBS_NUM_NODES\"\n))\n\noplan <- future::plan()\n\n## Use eager futures by default\nfuture::plan(\"sequential\")\n\n## Private future.apply functions\nfold <- future.apply:::fold\nhpaste <- future.apply:::hpaste\nmdebug <- future.apply:::mdebug\nmdebugf <- future.apply:::mdebugf\nimport_from <- future.apply:::import_from\nget_random_seed <- future.apply:::get_random_seed\nset_random_seed <- future.apply:::set_random_seed\nnext_random_seed <- future.apply:::next_random_seed\nas_lecyer_cmrg_seed <- future.apply:::as_lecyer_cmrg_seed\nis_lecyer_cmrg_seed <- future.apply:::is_lecyer_cmrg_seed\nmake_rng_seeds <- future.apply:::make_rng_seeds\n\n## Local functions for test scripts\nprintf <- function(...) cat(sprintf(...))\nmstr <- function(...) message(paste(capture.output(str(...)), collapse = \"\\n\"))\nattachLocally <- function(x, envir = parent.frame()) {\n  for (name in names(x)) {\n    assign(name, value = x[[name]], envir = envir)\n  }\n}\n\nsupportedStrategies <- function(cores = 1L, excl = c(\"cluster\"), ...) {\n  strategies <- future:::supportedStrategies(...)\n  strategies <- setdiff(strategies, excl)\n  if (cores > 1) {\n    strategies <- setdiff(strategies, c(\"sequential\", \"uniprocess\"))\n  }\n  strategies\n}\n\navailCores <- min(2L, future::availableCores())\n"
  },
  {
    "path": "tests/test-fold.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-fold.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"fold\")\n"
  },
  {
    "path": "tests/test-future_Filter.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_Filter.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_Filter\")\n"
  },
  {
    "path": "tests/test-future_apply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_apply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_apply\")\n"
  },
  {
    "path": "tests/test-future_by.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_by.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_by\")\n"
  },
  {
    "path": "tests/test-future_eapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_eapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_eapply\")\n"
  },
  {
    "path": "tests/test-future_kernapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_kernapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_kernapply\")\n"
  },
  {
    "path": "tests/test-future_lapply,RNG.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_lapply,RNG.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_lapply,RNG\")\n"
  },
  {
    "path": "tests/test-future_lapply,globals.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_lapply,globals.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_lapply,globals\")\n"
  },
  {
    "path": "tests/test-future_lapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_lapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_lapply\")\n"
  },
  {
    "path": "tests/test-future_mapply,globals.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_mapply,globals.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_mapply,globals\")\n"
  },
  {
    "path": "tests/test-future_mapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_mapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_mapply\")\n"
  },
  {
    "path": "tests/test-future_replicate.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_replicate.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_replicate\")\n"
  },
  {
    "path": "tests/test-future_sapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_sapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_sapply\")\n"
  },
  {
    "path": "tests/test-future_tapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_tapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_tapply\")\n"
  },
  {
    "path": "tests/test-future_vapply.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-future_vapply.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"future_vapply\")\n"
  },
  {
    "path": "tests/test-globals,tricky2.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-globals,tricky2.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"globals,tricky2\")\n"
  },
  {
    "path": "tests/test-globals,tricky_recursive.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-globals,tricky_recursive.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"globals,tricky_recursive\")\n"
  },
  {
    "path": "tests/test-options,nested.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-options,nested.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"options,nested\")\n"
  },
  {
    "path": "tests/test-rng.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-rng.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"rng\")\n"
  },
  {
    "path": "tests/test-stdout.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-stdout.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"stdout\")\n"
  },
  {
    "path": "tests/test-utils.R",
    "content": "#! /usr/bin/env Rscript\n## This runs testme test script inst/testme/test-utils.R\n## Don't edit - it was autogenerated by inst/testme/deploy.R\nfuture.apply:::testme(\"utils\")\n"
  },
  {
    "path": "vignettes/future.apply-1-overview.md.rsp",
    "content": "<%@meta language=\"R-vignette\" content=\"--------------------------------\n%\\VignetteIndexEntry{A Future for R: Apply Function to Elements in Parallel}\n%\\VignetteAuthor{Henrik Bengtsson}\n%\\VignetteKeyword{R}\n%\\VignetteKeyword{package}\n%\\VignetteKeyword{vignette}\n%\\VignetteKeyword{future}\n%\\VignetteKeyword{lazy evaluation}\n%\\VignetteKeyword{synchronous}\n%\\VignetteKeyword{asynchronous}\n%\\VignetteKeyword{parallel}\n%\\VignetteKeyword{cluster}\n%\\VignetteEngine{R.rsp::rsp}\n%\\VignetteTangle{FALSE}\n--------------------------------------------------------------------\"%>\n# A Future for R: Apply Function to Elements in Parallel\n\n## Introduction\n\nThe purpose of this package is to provide worry-free parallel alternatives to base-R \"apply\" functions, e.g. `apply()`, `lapply()`, and `vapply()`.  The goal is that one should be able to replace any of these in the core with its futurized equivalent and things will just work.  For example, instead of doing:\n```r\nlibrary(datasets)\nlibrary(stats)\ny <- lapply(mtcars, FUN = mean, trim = 0.10)\n```\none can do:\n```r\nlibrary(future.apply)\nplan(multisession) ## Run in parallel on local computer\n\nlibrary(datasets)\nlibrary(stats)\ny <- future_lapply(mtcars, FUN = mean, trim = 0.10)\n```\n\nReproducibility is part of the core design, which means that perfect, parallel random number generation (RNG) is supported regardless of the amount of chunking, type of load balancing, and future backend being used.  To enable parallel RNG, use argument `future.seed = TRUE`.\n\n\n## Role\n\nWhere does the **[future.apply]** package fit in the software stack?  You can think of it as a sibling to **[foreach]**, **[furrr]**, **[BiocParallel]**, **[plyr]**, etc.  Just as **parallel** provides `parLapply()`, **foreach** provides `foreach()`, **BiocParallel** provides `bplapply()`, and **plyr** provides `llply()`, **future.apply** provides `future_lapply()`.  Below is a table summarizing this idea:\n\n<table>\n<tr>\n<th>Package</th>\n<th>Functions</th>\n<th>Backends</th>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=future.apply\"><strong>future.apply</strong></a><br>\n<br>\n</td>\n<td>\nFuture-versions of common goto <code>*apply()</code> functions available in base R (of the <strong>base</strong> and <strong>stats</strong> packages):<br>\n<code>future_apply()</code>, \n<code>future_by()</code>, \n<code>future_eapply()</code>, \n<code>future_Filter()</code>, \n<code>future_lapply()</code>, \n<code>future_kernapply()</code>,\n<code>future_Map()</code>, \n<code>future_mapply()</code>, \n<code>future_.mapply()</code>, \n<code>future_replicate()</code>,\n<code>future_sapply()</code>,\n<code>future_tapply()</code>, and\n<code>future_vapply()</code>.\n<br>\n<em>The following function is not implemented:</em><br>\n<code>future_rapply()</code><br>\n</td>\n<td>\nAll <strong>future</strong> backends\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<strong>parallel</strong>\n</td>\n<td>\n<code>mclapply()</code>, <code>mcmapply()</code>,\n<code>clusterMap()</code>, <code>parApply()</code>, <code>parLapply()</code>, <code>parSapply()</code>, ...\n</td>\n<td>\nBuilt-in and conditional on operating system</a>\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=foreach\"><strong>foreach</strong></a>\n</td>\n<td>\n<code>foreach()</code>,\n<code>times()</code>\n</td>\n<td>\nAll <strong>future</strong> backends via <a href=\"https://cran.r-project.org/package=doFuture\"><strong>doFuture</strong></a>\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=furrr\"><strong>furrr</strong></a>\n</td>\n<td>\n<code>future_imap()</code>,\n<code>future_map()</code>,\n<code>future_pmap()</code>,\n<code>future_map2()</code>,\n...\n</td>\n<td>\nAll <strong>future</strong> backends\n</td>\n</tr>\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://bioconductor.org/packages/release/bioc/html/BiocParallel.html\"><strong>BiocParallel</strong></a>\n</td>\n<td>\nBioconductor's parallel mappers:<br>\n<code>bpaggregate()</code>,\n<code>bpiterate()</code>,\n<code>bplapply()</code>, and\n<code>bpvec()</code>\n</td>\n<td>\nAll <strong>future</strong> backends via <a href=\"https://cran.r-project.org/package=doFuture\"><strong>doFuture</strong></a> (because it supports <strong>foreach</strong>) or via <a href=\"https://github.com/futureverse/BiocParallel.FutureParam\"><strong>BiocParallel.FutureParam</strong></a> (direct BiocParallelParam support; prototype)\n</td>\n</tr>\n\n\n<tr style=\"vertical-align: top\">\n<td>\n<a href=\"https://cran.r-project.org/package=plyr\"><strong>plyr</strong></a>\n</td>\n<td>\n<code>**ply(..., .parallel = TRUE)</code> functions:<br>\n<code>aaply()</code>,\n<code>ddply()</code>,\n<code>dlply()</code>,\n<code>llply()</code>, ...\n</td>\n<td>\nAll <strong>future</strong> backends via <a href=\"https://cran.r-project.org/package=doFuture\"><strong>doFuture</strong></a> (because it uses <strong>foreach</strong> internally)\n</td>\n</tr>\n\n</table>\n\nNote that, except for the built-in **parallel** package, none of these higher-level APIs implement their own parallel backends, but they rather enhance existing ones.  The **foreach** framework leverages backends such as **[doParallel]**, **[doMC]** and **[doFuture]**, and the **future.apply** framework leverages the **[future]** ecosystem and therefore backends such as built-in **parallel**, **[future.callr]**, and **[future.batchtools]**.\n\nBy separating `future_lapply()` and friends from the **[future]** package, it helps clarifying the purpose of the **future** package, which is to define and provide the core Future API, which higher-level parallel APIs can build on and for which any futurized parallel backends can be plugged into.\n\nThe API and identity of the **future.apply** package will be kept close to the `*apply()` functions in base R.  In other words, it will _neither_ keep growing nor be expanded with new, more powerful apply-like functions beyond those core ones in base R.  Such extended functionality should be part of a separate package.\n\n\n[batchtools]: https://cran.r-project.org/package=batchtools\n[BiocParallel]: https://bioconductor.org/packages/BiocParallel/\n[doFuture]: https://cran.r-project.org/package=doFuture\n[doMC]: https://cran.r-project.org/package=doMC\n[doParallel]: https://cran.r-project.org/package=doParallel\n[foreach]: https://cran.r-project.org/package=foreach\n[future]: https://cran.r-project.org/package=future\n[future.apply]: https://cran.r-project.org/package=future.apply\n[future.batchtools]: https://cran.r-project.org/package=future.batchtools\n[future.callr]: https://cran.r-project.org/package=future.callr\n[furrr]: https://cran.r-project.org/package=furrr\n[plyr]: https://cran.r-project.org/package=plyr\n"
  }
]