'Difference between applying a function() to list() and to new.env()?

Why do I get two different results if I print x$val? I get that the first one is a list and the second is an environment, but I do not understand what makes the result of x$val from the second chunk = NA

x <- list()
x$val <- 1
myfun <- function(x) {x$val <- x$val + NA} 
myfun(x)
x$val
##[1] 1
x <- new.env()
x$val <- 18
myfun <- function(x) {x$val <- x$val + NA} 
myfun(x)
x$val
##[1] NA


Solution 1:[1]

Environments are "reference objects" in R. That means that if you assign one to a new variable, changes to either copy will affect both copies. Lists are like most other objects and get copied on assignment.

So in your first example, myfun(x) makes a separate copy of the list x, and works on that in the function. It has no effect on the global variable x.

In your second example, myfun(x) makes a new reference to the environment x, and works on that in the function. That affects the original variable as well.

Solution 2:[2]

Ok, based on the legit comment of the risk of using <<- some examples.

risky solution

x <- list("val" = 1L)
myfun <- function(x) {x$val <<- x$val + NA} 
myfun(x)
x
# $val
# [1] NA

risky solution going terribly wrong

x <- list("val" = "Please do not alter me at all")
y <- list("val" = 1L)
myfun <- function(x) {x$val <<- x$val + NA} 
myfun(y)
x
# $val
# [1] NA
y
# $val
# [1] 1

let your function output your data

x <- list("val" = 1L)
myfun <- function(x) list("val" = x$val + NA)
x <- myfun(x)
x
# $val
# [1] NA

use the environment

y  <- new.env()
y$val <- 18L
myfun <- function(x) {x$val <- x$val + NA} 
myfun(y)
y$val
# [1] NA

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user2554330
Solution 2