Why Does Rm Inside a Function Not Delete Objects

rm(list = ls()) doesn't work inside a function. Why?

rm is actually working, however since you're using it inside a function, it only removes all objects pertaining to the environment of that function.

Add envir = .GlobalEnv parameter to both calls:

rm(list = ls(envir = .GlobalEnv), envir = .GlobalEnv)

should do it.

I also recommend you take a look at this other question about gc() as i believe it's not a good practice to call it explicitly unless you really need it.

Use rm function in function

When you pass rm() a named object such as val, it will attempt to remove the object named val in the specified environment. However, you can use rm()'s "list" option to give it a character vector of names of objects to remove; from help("rm"):

Arguments

... the objects to be removed, as names (unquoted) or character
strings (quoted).

list a character vector naming objects to be
removed.

So, we do this:

rm_wrapper <- function(val, envi){rm(list = val, envir = envi)}
env <- new.env()
assign("v", 3, envir = env)
rm_wrapper("v", env)
ls(env)
# character(0)

We could alternatively make sure the character vectors you're sending your rm() wrapper are not named objects, like so:

rm_wrapper <- function(..., envi){rm(..., envir = envi)}
env <- new.env()
assign("v", 3, envir = env)
rm_wrapper("v", envi = env)
ls(env)
# character(0)

When is it worth using `remove` in R functions?

From Hadley Wickham's advanced R :

In some languages, you have to explicitly delete unused objects for
their memory to be returned. R uses an alternative approach: garbage
collection (or GC for short). GC automatically releases memory when an
object is no longer used. It does this by tracking how many names
point to each object, and when there are no names pointing to an
object, it deletes that object.

In the case you're describing garbage collection will release the memory.

In case the output of your function is another function, in which case Hadley names these functions respectively the function factory and the manufactured function, the variables created in the body of the function factory will be available in the enclosing environment of the manufactured function, and memory won't be freed.

More info, still in Hadley's book, can be found in the chapter about function factories.

function_factory <- function(x){
force(x)
y <- "bar"
fun <- function(z){
sprintf("x, y, and z are all accessible and their values are '%s', '%s', and '%s'",
x, y, z)
}
fun
}

manufactured_function <- function_factory("foo")
manufactured_function("baz")
#> [1] "x, y, and z are all accessible and their values are 'foo', 'bar', and 'baz'"

Created on 2019-07-08 by the reprex package (v0.3.0)

In this case, if you want to control which variables are available in the enclosing environment, or be sure you don't clutter your memory, you might want to remove unnecessary objects, either by using rm / remove as you did, or as I tend to prefer, wrapped in an on.exit statement.

Another case in which I might use rm is if I want to access variables from a parent environment without risk of them being overriden inside of the function, but in that case it's often possible and cleaner to use eval.parent.

y <- 2
z <- 3
test0 <- function(x, var){
y <- 1
x + eval(substitute(var))
}

# opps, the value of y is the one defined in the body
test0(0, y)
#> [1] 1
test0(0, z)
#> [1] 3

# but it will work using eval.parent :
test1 <- function(x, var){
y <- 1
x + eval.parent(substitute(var))
}
test1(0, y)
#> [1] 2
test1(0, z)
#> [1] 3

# in some cases (better avoided), it can be easier/quick and dirty to do something like :
test2 <- function(x, var){
y <- 1
# whatever code using y
rm(y)
x + eval(substitute(var))
}
test2(0, y)
#> [1] 2
test2(0, z)
#> [1] 3

Created on 2019-07-08 by the reprex package (v0.3.0)

R remove objects without throwing an error if they don't exist

Use suppressWarnings

suppressWarnings(rm(a,b,c,d))

Remove multiple objects with rm()

Make the list a character vector (not a vector of names)

rm(list = c('temp1','temp2'))

or

rm(temp1, temp2)

How can I remove all objects but one from the workspace in R?

Here is a simple construct that will do it, by using setdiff:

rm(list=setdiff(ls(), "x"))

And a full example. Run this at your own risk - it will remove all variables except x:

x <- 1
y <- 2
z <- 3
ls()
[1] "x" "y" "z"

rm(list=setdiff(ls(), "x"))

ls()
[1] "x"

Delete object after using it in function C++

You would do so by deleting this within AnObject::Foo but I would strongly discourage you from doing so. In this case, you do not need pointers at all:

class AnObject{
public:
AnObject Foo(){
return AnObject{};
}
};

int main()
{
AnObject x{};
AnObject result = x.Foo();
return 0;
}

If for whatever reason you really do need pointers, consider smart pointers

#include <memory>
class AnObject{
public:
std::unique_ptr<AnObject> Foo(){
return std::make_unique<AnObject>();
}
};

int main()
{
std::unique_ptr<AnObject> x = std::make_unique<AnObject>();
std::unique_ptr<AnObject> result = x->Foo();
return 0;
}

In both cases, you do not need to delete anything as you are using RAII semantics to handle your memory cleanup via scope.

Remove objects in .GlobalEnv from within a function

ls() needs to look in the correct place. By default it looks in the current frame, that of the function CleanEnvir in your case and hence was only finding "pattern" in your original.

CleanEnvir <- function(pattern = "tmp") {
objs <- ls(pos = ".GlobalEnv")
rm(list = objs[grep("tmp", objs)], pos = ".GlobalEnv")
}

Which gives:

> CleanEnvir <- function(pattern = "tmp") {
+ objs <- ls(pos = ".GlobalEnv")
+ rm(list = objs[grep("tmp", objs)], pos = ".GlobalEnv")
+ }
> ls()
[1] "CleanEnvir" "foo" "keep"
[4] "tmp.to.be.removed"
> CleanEnvir()
> ls()
[1] "CleanEnvir" "foo" "keep"


Related Topics



Leave a reply



Submit