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.
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
Hi Kevin,
Something like that would work: I actually just figured out this morning to use substitute while your comment was stuck in my spam filter. I’ll have to think whether your temp variable for the return value of pop approach is better than the temporary environment I wound up using. It seems like it should work, and it’s definitely simpler.
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)
}
}