Search code examples
rerror-checking

R - checking for existence of objects in a function


Suppose I have a set of variables x, y that may or may not be defined. These variables get passed into a function called test.

y <- 10
test <- function(a,b) { ifelse(a > b, "hello", "world") }
test(x,y)

# Error in ifelse(a > b, "hello", "world") : object 'x' not found

If I called test(x,y) when x hasn't been instantiated, R will throw an "object 'x' not found" error.

If I add in an exists check, the function works when calling it from a global environment

y <- 10
test <- function(a,b) { 
     print(exists(as.character(substitute(a))))
     if (!exists(as.character(substitute(a)))) {a <- 0}
     ifelse(a > b, "hello", "world")  
}
test(x,y)

# [1] FALSE
# [1] "world"

x <- 11
test(x,y)

[1] TRUE
[1] "hello"

However, if I wrap test(x,y) inside a the blah function. It fails to find the existing variable.

rm(list=ls())
test <- function(a,b) { 
     print(exists(as.character(substitute(a))))
     if (!exists(as.character(substitute(a)))) {a <- 0}
     ifelse(a > b, "hello", "world")  
}
blah <- function() { x <- 11; y <- 10; test(x,y)}
blah()
[1] FALSE -- expecting TRUE
[1] "world" -- expecting "hello"

I'm guessing the failure is due to it not looking in the right environment. Any idea how I can get this working properly?


Solution

  • You can specify in which environment you are looking first:

    test <- function(a,b) { 
         print(exists(as.character(substitute(a)), envir=parent.frame()))
         if (!exists(as.character(substitute(a)), envir=parent.frame())) {a <- 0}
         ifelse(a > b, "hello", "world")  
    }
    

    This way:

    y <- 10
    test(x,y)
    
    # [1] FALSE
    # [1] "world"
    
    x <- 11
    test(x,y)
    
    #[1] TRUE
    #[1] "hello"
    
    rm(list=ls())
    
    test <- function(a,b) { 
         print(exists(as.character(substitute(a)), envir=parent.frame()))
         if (!exists(as.character(substitute(a)), envir=parent.frame())) {a <- 0}
         ifelse(a > b, "hello", "world")  
    }
    blah <- function() { x <- 11; y <- 10; test(x,y)}
    blah()
    
    #[1] TRUE
    #[1] "hello"