{"id":22929619,"url":"https://github.com/futureverse/listenv","last_synced_at":"2026-02-13T08:32:14.738Z","repository":{"id":32322587,"uuid":"35897841","full_name":"futureverse/listenv","owner":"futureverse","description":"R package: listenv - Environments Behaving As Lists","archived":false,"fork":false,"pushed_at":"2025-04-19T16:49:09.000Z","size":1566,"stargazers_count":32,"open_issues_count":6,"forks_count":2,"subscribers_count":4,"default_branch":"develop","last_synced_at":"2025-07-08T04:51:18.030Z","etag":null,"topics":["package","r"],"latest_commit_sha":null,"homepage":"https://listenv.futureverse.org","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"Muratovm/Sergey","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/futureverse.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-05-19T17:33:24.000Z","updated_at":"2025-04-10T20:58:19.000Z","dependencies_parsed_at":"2024-02-26T01:49:00.644Z","dependency_job_id":"ca88d3dc-b657-4237-9df8-bc63e793666b","html_url":"https://github.com/futureverse/listenv","commit_stats":{"total_commits":305,"total_committers":2,"mean_commits":152.5,"dds":"0.016393442622950838","last_synced_commit":"0b9715bff09fce62fbc94d5365dd4182c2e7fbb7"},"previous_names":["futureverse/listenv","henrikbengtsson/listenv"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/futureverse/listenv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureverse%2Flistenv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureverse%2Flistenv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureverse%2Flistenv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureverse%2Flistenv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/futureverse","download_url":"https://codeload.github.com/futureverse/listenv/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futureverse%2Flistenv/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265837531,"owners_count":23836557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["package","r"],"created_at":"2024-12-14T10:08:42.964Z","updated_at":"2026-02-13T08:32:14.730Z","avatar_url":"https://github.com/futureverse.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n\u003cdiv id=\"badges\"\u003e\u003c!-- pkgdown markup --\u003e\n\u003ca href=\"https://CRAN.R-project.org/web/checks/check_results_listenv.html\"\u003e\u003cimg border=\"0\" src=\"https://www.r-pkg.org/badges/version/listenv\" alt=\"CRAN check status\"/\u003e\u003c/a\u003e \u003ca href=\"https://github.com/futureverse/listenv/actions?query=workflow%3AR-CMD-check\"\u003e\u003cimg border=\"0\" src=\"https://github.com/futureverse/listenv/actions/workflows/R-CMD-check.yaml/badge.svg?branch=develop\" alt=\"R CMD check status\"/\u003e\u003c/a\u003e     \u003ca href=\"https://app.codecov.io/gh/futureverse/listenv\"\u003e\u003cimg border=\"0\" src=\"https://codecov.io/gh/futureverse/listenv/branch/develop/graph/badge.svg\" alt=\"Coverage Status\"/\u003e\u003c/a\u003e \n\u003c/div\u003e\n\n# listenv: Environments Behaving (Almost) as Lists \n\n## Summary\n\n_List environments_ are environments that have list-like properties.  They are implemented by the [listenv] package.  The main features of a list environment are summarized in the below table:\n\n| Property                                                                     | list environments |  lists | environments |\n|------------------------------------------------------------------------------|:-----------------:|:------:|:------------:|\n| Number of elements, e.g. `length()`                                          |              yes  |   yes  |         yes  |\n| Named elements, e.g. `names()`, `x$a` and `x[[\"a\"]]`                         |              yes  |   yes  |         yes  |\n| Duplicated names                                                             |              yes  |   yes  |              |\n| Element names are optional                                                   |              yes  |   yes  |              |\n| Indexed elements, e.g. `x[[4]]`                                              |              yes  |   yes  |              |\n| Dimensions, e.g. `dim(x)`, `t(x)`, and `aperm(x, c(3,1,2))`                  |              yes  |   yes  |              |\n| Names of dimensions, e.g. `dimnames(x)`                                      |              yes  |   yes  |              |\n| Indexing by dimensions, e.g. `x[[2, 4]]` and `x[[2, \"D\"]]`                   |              yes  |   yes  |              |\n| Multi-element subsetting, e.g. `x[c(\"a\", \"c\")]`, `x[-1]` and `x[2:1, , 3]`   |              yes  |   yes  |              |\n| Multi-element subsetting preserves element names                             |              yes  |        |              |\n| Resizing, e.g. `length(x) \u003c- 6`                                              |              yes  |   yes  |              |\n| Removing elements by assigning NULL, e.g. `x$c \u003c- NULL` and `x[1:3] \u003c- NULL` |              yes  |   yes  |              |\n| Removing parts of dimensions by assigning NULL, e.g. `x[,2] \u003c- NULL`         |              yes  |        |              |\n| Mutable, e.g. `y \u003c- x; y$a \u003c- 3; identical(y, x)`                            |              yes  |        |         yes  |\n| Compatible* with `assign()`, `delayedAssign()`, `get()` and `exists()`       |              yes  |        |         yes  |\n\nFor example,\n```r\n\u003e x \u003c- listenv(a = 1, b = 2, c = \"hello\")\n\u003e x\nA ‘listenv’ vector with 3 elements (‘a’, ‘b’, ‘c’).\n\u003e length(x)\n[1] 3\n\u003e names(x)\n[1] \"a\" \"b\" \"c\"\n\u003e x$a\n[1] 1\n\u003e x[[3]] \u003c- toupper(x[[3]])\n\u003e x$c\n[1] \"HELLO\"\n\u003e y \u003c- x\n\u003e y$d \u003c- y$a + y[[\"b\"]]\n\u003e names(y)[2] \u003c- \"a\"\n\u003e y$a\n[1] 1\n\u003e y\nA ‘listenv’ vector with 4 elements (‘a’, ‘a’, ‘c’, ‘d’).\n\u003e identical(y, x)\n[1] TRUE\n\u003e for (ii in seq_along(x)) {\n+     cat(sprintf(\"Element %d (%s): %s\\n\", ii, sQuote(names(x)[ii]), \n+         x[[ii]]))\n+ }\nElement 1 (‘a’): 1\nElement 2 (‘a’): 2\nElement 3 (‘c’): HELLO\nElement 4 (‘d’): 3\n\u003e x[c(1, 3)] \u003c- list(2, \"Hello world!\")\n\u003e x\nA ‘listenv’ vector with 4 elements (‘a’, ‘a’, ‘c’, ‘d’).\n\u003e y \u003c- as.list(x)\n\u003e str(y)\nList of 4\n $ a: num 2\n $ a: num 2\n $ c: chr \"Hello world!\"\n $ d: num 3\n\u003e z \u003c- as.listenv(y)\n\u003e z\nA ‘listenv’ vector with 4 elements (‘a’, ‘a’, ‘c’, ‘d’).\n\u003e identical(z, x)\n[1] FALSE\n\u003e all.equal(z, x)\n[1] TRUE\n```\n\n## Creating list environments\nList environments are created similarly to lists but also similarly to environments.  To create an empty list environment, use\n```r\n\u003e x \u003c- listenv()\n\u003e x\nA ‘listenv’ vector with 0 elements (unnamed).\n```\nThis can later be populated using named assignments,\n```r\n\u003e x$a \u003c- 1\n\u003e x\nA ‘listenv’ vector with 1 element (‘a’).\n```\ncomparable to how both lists and environments work.  Similarly to lists, they can also be populated using indices, e.g.\n```r\n\u003e x[[2]] \u003c- 2\n\u003e x$c \u003c- 3\n\u003e x\nA ‘listenv’ vector with 3 elements (‘a’, ‘’, ‘c’).\n```\nJust as for lists, a list environment is expanded with `NULL` elements whenever a new element is added that is beyond the current length plus one, e.g.\n```r\n\u003e x[[5]] \u003c- 5\n\u003e x\nA ‘listenv’ vector with 5 elements (‘a’, ‘’, ‘c’, ‘’, ‘’).\n\u003e x[[4]]\nNULL\n```\n\nAs with lists, the above list environment can also be created from the start, e.g.\n```r\n\u003e x \u003c- listenv(a = 1, 3, c = 4, NULL, 5)\n\u003e x\nA ‘listenv’ vector with 5 elements (‘a’, ‘’, ‘c’, ‘’, ‘’).\n```\n\n\nAs for lists, the length of a list environment can at any time be increased or decreased by assigning it a new length.\nIf decreased, elements are dropped, e.g.\n```r\n\u003e x\nA ‘listenv’ vector with 5 elements (‘a’, ‘’, ‘c’, ‘’, ‘’).\n\u003e length(x) \u003c- 2\n\u003e x\nA ‘listenv’ vector with 2 elements (‘a’, ‘’).\n\u003e x[[1]]\n[1] 1\n\u003e x[[2]]\n[1] 3\n```\nIf increased, new elements are populated with unnamed elements of `NULL`, e.g.\n```r\n\u003e length(x) \u003c- 4\n\u003e x\nA ‘listenv’ vector with 4 elements (‘a’, ‘’, ‘’, ‘’).\n\u003e x[[3]]\nNULL\n\u003e x[[4]]\nNULL\n```\n\nTo allocate an \"empty\" list environment (with all `NULL`:s) of a given length, do\n```r\n\u003e x \u003c- listenv()\n\u003e length(x) \u003c- 4\n\u003e x\nA ‘listenv’ vector with 4 elements (unnamed).\n```\n_Note_: Unfortunately, it is _not_ possible to use `x \u003c- vector(\"listenv\", length = 4)`; that construct is only supported for the basic data types.\n\nElements can be dropped by assigning `NULL`, e.g. to drop the first and third element of a list environment, do:\n```r\n\u003e x[c(1, 3)] \u003c- NULL\n\u003e x\nA ‘listenv’ vector with 2 elements (unnamed).\n```\n\n\n## Iterating over elements\n\n### Iterating over elements by names\nAnalogously to lists and plain environments, it is possible to iterate over elements of list environments by the element names.  For example,\n```r\n\u003e x \u003c- listenv(a = 1, b = 2, c = 3)\n\u003e for (name in names(x)) {\n+     cat(sprintf(\"Element %s: %s\\n\", sQuote(name), x[[name]]))\n+ }\nElement ‘a’: 1\nElement ‘b’: 2\nElement ‘c’: 3\n```\n\n### Iterating over elements by indices\nAnalogously to lists, but contrary to plain environments, it is also possible to iterate over elements by their indices.  For example,\n```r\n\u003e x \u003c- listenv(a = 1, b = 2, c = 3)\n\u003e for (ii in seq_along(x)) {\n+     cat(sprintf(\"Element %d: %s\\n\", ii, x[[ii]]))\n+ }\nElement 1: 1\nElement 2: 2\nElement 3: 3\n```\n\n\n## Coercion to and from list environments\n\n### Coercing to lists and vectors\n\nCoercing a list environment to a list:\n```r\n\u003e x \u003c- listenv(a = 2, b = 3, c = \"hello\")\n\u003e x\nA ‘listenv’ vector with 3 elements (‘a’, ‘b’, ‘c’).\n\u003e y \u003c- as.list(x)\n\u003e str(y)\nList of 3\n $ a: num 2\n $ b: num 3\n $ c: chr \"hello\"\n```\n\nCoercing a list to a list environment:\n```r\n\u003e z \u003c- as.listenv(y)\n\u003e z\nA ‘listenv’ vector with 3 elements (‘a’, ‘b’, ‘c’).\n\u003e identical(z, x)\n[1] FALSE\n\u003e all.equal(z, x)\n[1] TRUE\n```\n\nUnlisting:\n```r\n\u003e unlist(x)\n      a       b       c \n    \"2\"     \"3\" \"hello\" \n\u003e unlist(x[-3])\na b \n2 3 \n\u003e unlist(x[1:2], use.names = FALSE)\n[1] 2 3\n```\n\n\n## Multi-dimensional list environments\n\nAnalogously to lists, and contrary to plain environments, list environments can have dimensions with corresponding names.  For example,\n```r\n\u003e x \u003c- as.listenv(1:6)\n\u003e dim(x) \u003c- c(2, 3)\n\u003e dimnames(x) \u003c- list(c(\"a\", \"b\"), c(\"A\", \"B\", \"C\"))\n\u003e x\nA ‘listenv’ matrix with 6 elements (unnamed) arranged in 2x3 rows (‘a’, ‘b’) and columns (‘A’, ‘B’, ‘C’).\n```\nAn easy way to quickly get an overview is to coerce to a list, e.g.\n```r\n\u003e as.list(x)\n  A B C\na 1 3 5\nb 2 4 6\n```\nIndividual elements of a list environment can be accessed using standard subsetting syntax, e.g.\n```r\n\u003e x[[\"a\", \"B\"]]\n[1] 3\n\u003e x[[1, 2]]\n[1] 3\n\u003e x[[1, \"B\"]]\n[1] 3\n```\nWe can assign individual elements similarly, e.g.\n```r\n\u003e x[[\"b\", \"B\"]] \u003c- -x[[\"b\", \"B\"]]\n\u003e as.list(x)\n  A B  C\na 1 3  5\nb 2 -4 6\n```\nWe can also assign multiple elements through dimensional subsetting, e.g.\n```r\n\u003e x[2, -1] \u003c- 98:99\n\u003e as.list(x)\n  A B  C \na 1 3  5 \nb 2 98 99\n\u003e x[\"a\", c(1, 3)] \u003c- list(97, \"foo\")\n\u003e as.list(x)\n  A  B  C    \na 97 3  \"foo\"\nb 2  98 99   \n\u003e x[] \u003c- 1:6\n\u003e as.list(x)\n  A B C\na 1 3 5\nb 2 4 6\n```\n\nConcurrently with dimensional names it is possible to have names of the individual elements just as for list environments without dimensions.  For example,\n```r\n\u003e names(x) \u003c- letters[seq_along(x)]\n\u003e x\nA ‘listenv’ matrix with 6 elements (‘a’, ‘b’, ‘c’, ..., ‘f’) arranged in 2x3 rows (‘a’, ‘b’) and columns (‘A’, ‘B’, ‘C’).\n\u003e x[[\"a\"]]\n[1] 1\n\u003e x[[\"f\"]]\n[1] 6\n\u003e x[c(\"a\", \"f\")]\nA ‘listenv’ vector with 2 elements (‘a’, ‘f’).\n\u003e unlist(x)\na b c d e f \n1 2 3 4 5 6 \n\u003e as.list(x)\n  A B C\na 1 3 5\nb 2 4 6\nattr(,\"names\")\n[1] \"a\" \"b\" \"c\" \"d\" \"e\" \"f\"\n```\nContrary to lists, element names are preserved also with multi-dimensional subsetting, e.g.\n```r\n\u003e x[1, 2]\nA ‘listenv’ vector with 1 element (‘c’).\n\u003e x[1, 2, drop = FALSE]\nA ‘listenv’ matrix with 1 element (‘c’) arranged in 1x1 rows (‘a’) and columns (‘B’).\n\u003e x[1:2, 2:1]\nA ‘listenv’ matrix with 4 elements (‘c’, ‘d’, ‘a’, ‘b’) arranged in 2x2 rows (‘a’, ‘b’) and columns (‘B’, ‘A’).\n\u003e x[2, ]\nA ‘listenv’ vector with 3 elements (‘b’, ‘d’, ‘f’).\n\u003e x[2, , drop = FALSE]\nA ‘listenv’ matrix with 3 elements (‘b’, ‘d’, ‘f’) arranged in 1x3 rows (‘b’) and columns (‘A’, ‘B’, ‘C’).\n\u003e x[\"b\", -2, drop = FALSE]\nA ‘listenv’ matrix with 2 elements (‘b’, ‘f’) arranged in 1x2 rows (‘b’) and columns (‘A’, ‘C’).\n```\n\n\nNote, whenever dimensions are set using `dim(x) \u003c- dims` both the dimensional names and the element names are removed, e.g.\n```r\n\u003e dim(x) \u003c- NULL\n\u003e names(x)\nNULL\n```\nThis behavior is by design, cf. `help(\"dim\", package=\"base\")`.\n\n\nTo allocate an \"empty\" list environment array (with all `NULL`:s) of a given dimension, do\n```r\n\u003e x \u003c- listenv()\n\u003e dim(x) \u003c- c(2, 3)\n\u003e dimnames(x) \u003c- list(c(\"a\", \"b\"), c(\"A\", \"B\", \"C\"))\n\u003e x\nA ‘listenv’ matrix with 6 elements (unnamed) arranged in 2x3 rows (‘a’, ‘b’) and columns (‘A’, ‘B’, ‘C’).\n```\nRows and columns can be dropped by assigning `NULL`, e.g. to drop the first and third column of a list-environment matrix, do:\n```r\n\u003e x[, c(1, 3)] \u003c- NULL\n\u003e x\nA ‘listenv’ matrix with 2 elements (unnamed) arranged in 2x1 rows (‘a’, ‘b’) and columns (‘B’).\n```\n\n\n\n\n## Important about environments\nList environments are as their name suggests _environments_.  Whenever working with environments in R, it is important to understand that _environments are mutable_ whereas all other of the basic data types in R are immutable.  For example, consider the following function that assigns zero to element `a` of object `x`:\n```r\n\u003e setA \u003c- function(x) {\n+     x$a \u003c- 0\n+     x\n+ }\n```\nIf we pass a regular list to this function,\n```r\n\u003e x \u003c- list(a = 1)\n\u003e y \u003c- setA(x)\n\u003e x$a\n[1] 1\n\u003e y$a\n[1] 0\n```\nwe see that `x` is unaffected by the assignment.  This is because _lists are immutable_ in R.  However, if we pass an environment instead,\n```r\n\u003e x \u003c- new.env()\n\u003e x$a \u003c- 1\n\u003e y \u003c- setA(x)\n\u003e x$a\n[1] 0\n\u003e y$a\n[1] 0\n```\nwe find that `x` was affected by the assignment.  This is because _environments are mutable_ in R.  Since list environments inherit from environments, this also goes for them, e.g.\n```r\n\u003e x \u003c- listenv(a = 1)\n\u003e y \u003c- setA(x)\n\u003e x$a\n[1] 0\n\u003e y$a\n[1] 0\n```\n\nWhat is also important to understand is that it is not just the _content_ of an environment that is mutable but also its _attributes_.  For example,\n```r\n\u003e x \u003c- listenv(a = 1)\n\u003e y \u003c- x\n\u003e attr(y, \"foo\") \u003c- \"Hello!\"\n\u003e attr(x, \"foo\")\n[1] \"Hello!\"\n```\nMore importantly, since dimensions and their names are also attributes, this also means they are mutable.  For example,\n```r\n\u003e x \u003c- as.listenv(1:6)\n\u003e dim(x) \u003c- c(2, 3)\n\u003e x\nA ‘listenv’ matrix with 6 elements (unnamed) arranged in 2x3 unnamed rows and columns.\n\u003e y \u003c- x\n\u003e dim(y) \u003c- c(3, 2)\n\u003e x\nA ‘listenv’ matrix with 6 elements (unnamed) arranged in 3x2 unnamed rows and columns.\n```\n\n\n[listenv]: https://cran.r-project.org/package=listenv\n\n\n## Installation\nR package listenv is available on [CRAN](https://cran.r-project.org/package=listenv) and can be installed in R as:\n```r\ninstall.packages(\"listenv\")\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/listenv\", ref=\"develop\")\n```\nThis will install the package from source.  \n\n\u003c!-- pkgdown-drop-below --\u003e\n\n\n## Contributing\n\nTo contribute to this package, please see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffutureverse%2Flistenv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffutureverse%2Flistenv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffutureverse%2Flistenv/lists"}