Implementing Push and Pop in R

Having grown up with Perl, there are two functions that I desperately miss while programming in R: push and pop. Continually writing

1
vector <- c(vector, new.entry)

tries my patience, while writing

1
2
vector <- rep(NA, inscrutable.constant)
vector[inscrutable.index] <- new.entry

makes me feel like I’m programming in C, rather than a higher-level programming language. That said, here’s a simplistic hack to provide something like an implementation of push and pop in R:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
push <- function(vector.name, item)
{
  eval.parent(parse(text = paste(vector.name, ' <- c(', vector.name, ', ', item, ')',
                                 sep = '')),
              n = 1)
}
 
pop <- function(vector.name)
{
  eval.parent(parse(text = paste(vector.name, ' <- ', 
                                 vector.name, '[-length(', vector.name, ')]',
                                 sep = '')),
              n = 1)
}

Both of these functions are more than a little ugly, because you have to pass in a string that names the vector you want to change, rather than providing its name as a bareword. Even worse, this version of pop doesn’t let you get the value of the item you pop off of the stack, because I’m not sure how to introduce a temporary variable into the parent’s environment without occasionally clobbering the value of an existing variable. If I knew more about scoping and lazy evaluation in R, I think I could implement these two functions as pseudo-macros and solve both concerns. If you know how to do this, please do let me know.

3 responses to “Implementing Push and Pop in R”

  1. Kevin Wright

    Does this do what you want?

    push <- function(vec, item) {
    vec=substitute(vec)
    eval.parent(parse(text = paste(vec, ' <- c(', vec, ', ', item, ')', sep = '')), n = 1)
    }
    pop <- function(vec) {
    tmp <- vec[length(vec)]
    vec=substitute(vec)
    eval.parent(parse(text = paste(vec, ' <- ', vec, '[-length(', vec, ')]',
    sep = '')),
    n = 1)
    tmp
    }
    kk=1:4
    kk
    push(kk,5)
    kk
    pop(kk)
    kk

  2. Iain S

    Kevin’s solution works nicely, except if you try pushing a string onto a vector. In that case, you need to enclose the item in quotes, as below:

    push = function(vec, item)
    {
    vec = substitute(vec)

    if (is(item, “character”)) {
    eval.parent(parse(text = paste(vec, ‘ <- c(', vec, ', "', item, '")', sep = '')), n=1)
    } else {
    eval.parent(parse(text = paste(vec, ' <- c(', vec, ', ', item, ')', sep = '')), n=1)
    }
    }