0

I have a function in R that should modify a list by appending new items to it. However I really do not want to make a copy of my list.

I know this is not an easy task in R, and I have seen some minimal examples using the eval.parent function, but I do not know how they would apply to my particular case.

A minimal example of my problem (not my actual function) would look like

L <- list(o1 = 1, o2 = 2, o3 = 3)
add_to_list <- function(L){
  n1 <- sum(unlist(L))
  n2 <- mean(unlist(L))
  L$n1 <- n1
  L$n2 <- n2
  return(L)
}
L <- add_to_list(L)

If I'm correct, as L is modified, the function add_to_list will make a full copy of L, including o1, o2, and o3, in this example? (It appears so when I look at the computation time of my actual function.)

I would like to pass L by reference as this would drastically increase the performance of my code. In my real example, there are more than three objects o1, o2, and o3, and some of them are really large, and I also have a lot of code before the final assignments which is why I want it modularized as function.

rvdaele
  • 114
  • 10
  • Best to show what you would like to get to get alternative answers. This can be done with `lapply`, no? – NelsonGon Apr 26 '19 at 12:21
  • 3
    This question about "whether appending will copy the list" may give you more insight https://stackoverflow.com/questions/12772522/does-appending-to-a-list-in-r-result-in-copying – CodeNoob Apr 26 '19 at 12:22
  • What about `L = c(L, n1=sum(unlist(L)), n2=mean(unlist(L)))` ? – Jet Apr 26 '19 at 12:37
  • Alternative is to use environment instead of a list. AFAIK, appending/assigning to environment doesn't make a copy. – Jav Apr 26 '19 at 13:00
  • The problem is that I would really need to do the appending in a function: just appending to a list might not make a copy in general, but modifying an item passed to a function will make a copy of that item (unless this is not the case in this particular example?). One liners are also not really an option, my real and not simplistic function has about 50 lines of code before I can finally append to my list, and the appended items are not independently computed from each other (doing that would increase the computation time even further). – rvdaele Apr 26 '19 at 13:21

1 Answers1

1

Actually, I think appending to lists does not make deep copies of the previous elements, you can test this with base R:

x <- 1:2
tracemem(x)

y <- 3:4

L <- list(x=x, y=y)

foo <- function(L) {
  L$z <- 5:6
  L
}

# no copy shown here
L <- foo(L)

# copy shown, x copied so that L$x stays unmodified
x[1L] <- 0L

Or with pryr:

library(pryr)

x <- 1:2
address(x)
[1] "0x26f5f344ba0"

foo <- function(L) {
  L$z <- 5:6
  L
}

L <- list(x=x)
L <- foo(L)
lx <- L$x

address(lx)
[1] "0x26f5f344ba0"
Alexis
  • 4,950
  • 1
  • 18
  • 37
  • You are right, I tested this and indeed, appending to a list does not copy the items even when performed inside a function, thanks :) – rvdaele Apr 28 '19 at 17:31