HenrikBengtsson / listenv

R package: listenv - Environments Behaving As Lists
https://listenv.futureverse.org
30 stars 2 forks source link

feature request: a method to modify listenv using another list/listenv #49

Open DyfanJones opened 2 years ago

DyfanJones commented 2 years ago

Hi @HenrikBengtsson,

Possible enhancement in having a function to modify existing listenv with another list/ listenv, similar to how the function utils::modifyList works.

Here is an example of what it could be like:

UPDATED Code Chunk: ----

library(listenv)

modifyListenv <- function (x, val, keep.null = FALSE) {
  stopifnot(
    inherits(x, "listenv") || is.list(x),
    inherits(val, "listenv") || is.list(val)
  )
  xnames <- names(x)
  vnames <- names(val)[nzchar(names(val))]
  if (keep.null) {
    for (v in vnames) {
      if (v %in% xnames
          && is.list(x[[v]])
          && (is.list(val[[v]]) || inherits(val[[v]], "listenv"))) {
        x[v] <- list(modifyListenv(x[[v]], val[[v]], keep.null = keep.null))
      } else if (v %in% xnames
          && inherits(x[[v]], "listenv")
          && (is.list(val[[v]]) || inherits(val[[v]], "listenv"))) {
        modifyListenv(x[[v]], val[[v]], keep.null = keep.null)
      } else {
        x[v] <- list(val[[v]])
      }
    }
  } else {
    for (v in vnames) {
      if (v %in% xnames
          && is.list(x[[v]])
          && (is.list(val[[v]]) || inherits(val[[v]], "listenv"))) {
        x[[v]] <- modifyListenv(x[[v]], val[[v]], keep.null = keep.null)
      } else if (v %in% xnames
          && inherits(x[[v]], "listenv")
          && (is.list(val[[v]]) || inherits(val[[v]], "listenv"))) {
        modifyListenv(x[[v]], val[[v]], keep.null = keep.null)
      } else {
        x[[v]] <- val[[v]]
      }
    }
  }
  x
}

X = listenv(a=7, c="dummy")
Y = listenv(a=6,b=10)
Z = listenv(d = NULL)

modifyListenv(X,Y)
#> A 'listenv' vector with 3 elements ('a', 'c', 'b').
as.list(X)
#> $a
#> [1] 6
#> 
#> $c
#> [1] "dummy"
#> 
#> $b
#> [1] 10

modifyListenv(X,Z, keep.null = T)
#> A 'listenv' vector with 4 elements ('a', 'c', 'b', 'd').
as.list(X)
#> $a
#> [1] 6
#> 
#> $c
#> [1] "dummy"
#> 
#> $b
#> [1] 10
#> 
#> $d
#> NULL

X = listenv(a=7, c="dummy")
Y = listenv(b=10, x = listenv(a=2))
Z = listenv(d = NULL, x= X)

modifyListenv(Z,Y)
#> A 'listenv' vector with 3 elements ('d', 'x', 'b').
as.list(Z$x)
#> $a
#> [1] 2
#> 
#> $c
#> [1] "dummy"

X = listenv(a=7, c="dummy", d = list(e=1,f=2,g=3))
Y = listenv(b=10, d = list(f=20))
modifyListenv(X,Y)
#> A 'listenv' vector with 4 elements ('a', 'c', 'd', 'b').
as.list(X$d)
#> $e
#> [1] 1
#> 
#> $f
#> [1] 20
#> 
#> $g
#> [1] 3

X = listenv(a=7, c="dummy", d = list(e=1,f=2,g=listenv(h = 1, i = 2)))
Y = listenv(b=10, d = list(f=20, g=listenv(h = 10)))
modifyListenv(X,Y)
#> A 'listenv' vector with 4 elements ('a', 'c', 'd', 'b').
as.list(X$d$g)
#> $h
#> [1] 10
#> 
#> $i
#> [1] 2

Created on 2022-05-27 by the reprex package (v2.0.1)

Alittle bit messy at the moment :S But seems to do what is required :)