spindash_st
spindash_st

Reputation: 442

Proper error handling of nested functions

I have a function superFoo() which calls other functions foo(). Each foo() functions has different outputs, i.e., lists, data-frame, scalar. I need to:

  1. Stop the execution of superFoo() whenever any foo() fails (it signals an error or warning)
  2. Capture the error message.

    foo = function(a){
        log(a)
    }
    
    superFoo = function (a){
        varA = foo(a)
    
        # IF foo(a) fails, superFoo has to: stop and     return NA
    
        varB = foo(varA+3)
        varA + varB
    }
    
    # Iteration
    HyperY = setups %>% split(.$IDsample) %>% 
        map(superFoo)
    

I know I can do tryCatch() inside superFoo(), capture the error message and return NA in superFoo(). Something like:

varA = tryCatch({foo()}, error=(return(NULL)), warning(return(NULL)))
if (is.null(varA)) { return(list(NA, errorMessage)}

The problem is that I have 9 functions foo() in superFoo(). I wonder if there is a more efficient way of programming this.

Another alternative is purrr:safely(). This is, however, as wordy as tryCatch() cause I have to redeclare foo() in superFoo() before calling it:

safeFoo = safely(foo)
varA = safeFoo(a)
if (is.null(varA)) { return(list(NA, errorMessage) }

What is a good practice of error handling in nested functions?

Upvotes: 1

Views: 1042

Answers (1)

user2554330
user2554330

Reputation: 44987

If you have the same response to any of the 9 function calls, then you can wrap the whole body of superFoo in one tryCatch, e.g.

superFoo = function (a){
  tryCatch({
    varA = foo(a)

    # IF foo(a) fails, superFoo has to: stop and     return NA

    varB = foo(varA+3)
    varA + varB
  }, error = return(NULL), warning = return(NULL))
}

This skips the separate check for is.null(varA). If you want that, add a line like

if (is.null(varA)) stop("varA is NULL")

and that will be caught the same as other errors are caught.

Upvotes: 1

Related Questions