A better way to push and pop to/from lists in R?

A few years late to the party, but here's the approach that requires the least amount of typing. Note that pop removes the last element from the object.

push <- function(obj, input) {
  variable <- deparse(substitute(obj))
  out <- get(variable, envir = parent.frame(n=2))
  out[[length(out)+1]] <- input
  assign(variable, out, envir = parent.frame(n=2))
}

pop <- function(obj) {
  variable <- deparse(substitute(obj))
  obj <- get(variable, envir = parent.frame(n=2))
  
  if (length(obj) > 0) {
    out <- obj[[length(obj)]]
    assign(variable, obj[-length(obj)], envir = parent.frame(n=2))
  }else{
    out <- NULL
    assign(variable, out, envir = parent.frame(n=2))
  }
  
  return(out)
}

Example:

> foo <- list()
> push(foo, "a")
> push(foo, "b")
> foo
[[1]]
[1] "a"

[[2]]
[1] "b"

> pop(foo)
[1] "b"
> foo
[[1]]
[1] "a"

pushR = function(foo, bar){
  foo[[length(foo)+1]] <- bar
  foo
}

popR=function(foo){
  foo[[length(foo)]]
}

foo <- list()
for (i in 1:10) {
  x <- data.frame(a=i, b=rnorm(1,0,1))
  foo <- pushR(foo, x)
}

popR(foo)

foo[[length(foo)+1]] <- bar

could be rewritten as

foo <- append(foo, bar)

and

bar <- foo[[length(foo)]]

could be rewritten as

bar <- tail(foo,1)

Note that with functional languages such as R functions generally aren't supposed to changes values of parameters passed to them; typically you return a new object which you can assign elsewhere. The function should have no "side effects." Functions like push/pop in other languages usually modify one of the passed parameters.

Tags:

R