7

I am trying to write a function that removes an object if it exists. The reason is that I want to get rid of the log-message Error: object 'arg' not found. I tried the following:

ifrm <- function(arg)
{
   if(exists(as.character(substitute(arg)))){rm(arg)}
}

Unfortunately this does not remove the object if it exists

> ifrm <- function(arg)
+ {
+    if(exists(as.character(substitute(arg)))){rm(arg)}
+ }
> a <- 2
> ifrm(a)
> a
[1] 2

Any hints what I do wrong here?

Best Albrecht

Tungurahua
  • 489
  • 7
  • 21
  • 2
    This sounds like a possibly dangerous thing to do. Do you want to give us a bit more detail about the circumstances where you get this error? There may be other ways of dealing with your error message that are more appropriate. – Andrie Aug 24 '11 at 08:39
  • 2
    I agree with Andrie. The answers provided will do what you asked, but most likely what you actually should be doing is even simpler. Take a look at try and trycatch. What is it that you're trying to do that is attempting to process nonexistent objects? – Carl Witthoft Aug 24 '11 at 11:22

4 Answers4

10

A general idiom to grab what the user supplied as an argument to a function is deparse(substitute(foo)). This function is similar to that of @Ian Ross but employing this standard idiom:

ifrm <- function(obj, env = globalenv()) {
    obj <- deparse(substitute(obj))
    if(exists(obj, envir = env)) {
        rm(list = obj, envir = env)
    }
}

where I assume you only ever want to remove objects from the global environment, hence the default, but you can supply an environment via env. And here it is in action:

> a <- 1:10
> ls()
[1] "a"    "ifrm"
> ifrm(a)
> ls()
[1] "ifrm"
> ifrm(a)
> ls()
[1] "ifrm"
Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
  • 2
    One should add a warning that using deparse(substitute()) in a nested function is bound to give trouble. myrm <- function(x) ifrm(x) will not do what you think it does... – Joris Meys Aug 24 '11 at 09:01
  • 2
    @Joris +1 good point, but then one could say, don't do that! ;-) – Gavin Simpson Aug 24 '11 at 09:10
7

Try this

 a=1; b=3; y=4; ls() 
 rm( list = Filter( exists, c("a", "b", "x", "y") ) )
 ls()
baptiste
  • 75,767
  • 19
  • 198
  • 294
4

Keep it simple. Just pass the name of the object into your function as a character string, rather than trying to get the name from the actual object.

ifrm <- function(x, env = globalenv()) 
{
  if(exists(x, envir = env)) 
  {
    rm(list = x, envir = env)
  }
}
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
3

This is kind of ugly, but it seems to work:

ifrm <- function(arg) {
  if (exists(as.character(substitute(arg)))) {
    rm(list=as.character(substitute(arg)), envir=sys.frame())
  }
}

You might want to specify the environment differently if you're not removing names from the top-level environment.

Ian Ross
  • 987
  • 8
  • 14