You can do it using pryr::promise_info(l)$env
, but it's a very un-R-like thing to do. Functions shouldn't have side effects.
For example,
pop <- function(l) {
info <- pryr::promise_info(l)
if (!is.name(info$code))
stop("Argument expression should be a name.")
result <- l[[1]] # work on lists too
assign(as.character(info$code), l[-1], envir = info$env)
result
}
l <- c(1, 3, 5)
pop(l)
#> Registered S3 method overwritten by 'pryr':
#> method from
#> print.bytes Rcpp
#> [1] 1
l
#> [1] 3 5
Created on 2020-08-15 by the reprex package (v0.3.0)
Edited to add: Interestingly, none of the three answers so far works in complicated situations like this one:
f <- function(x) {
cat("The pop(x) result is", pop(x), "\n")
cat("Now x is ", x, "\n")
cat("Now l is ", l, "\n")
}
l <- c(1, 3, 5)
f(l)
@RuiBarradas's answer gives
The pop(x) result is 5
Now x is 1 3 5
Now l is 1 3 5
(He pops the last value rather than the first which is not a big deal, but neither x
nor l
is modified.)
@AllanCameron's answer gives
The pop(x) result is 1
Now x is 3 5
Now l is 1 3 5
This is arguably correct (x
got popped), but I think it would be nice to have l
being popped, and that seems tricky.
My answer dies with this message:
Error in pop(x) : Argument expression should be a name.
which seems like a bug: obviously whether it's getting x
or l
, it really is a name. The problem seems to be in pryr::promise_info
, which returns the compiled code that would return the value of x
, rather than just the code for x
. If I turn off JIT compiling by compiler::enableJIT(0)
, I get the same result as @AllanCameron. It's not clear to me how to unwind back the right amount to pop l
instead of just x
.