minoo
minoo

Reputation: 575

using trycatch which returns the context of the error

Here I have this function: (remove object is the name of the functions that we do nt want to compute)

    func <- function(x, remove=NULL) {
  if(class(x)%in%"igraph"){
  doclist <- list("edgelist"=function(x) as.edgelist(x),
                    "adjacencyMatrix"=function(x)as_adjacency_matrix(x),
                    "incidenceMatrix"=function(x) as_incidence_matrix(x, 0.001),
                    "data.frame"=function(x) as_data_frame(x))

  sapply(doclist[setdiff(names(doclist), remove)], function(f) f(n))}
  else stop("The input is not an igraph object")
}

How can I use tryCatch in this function? If any functions in the 'doclist' faced an error, the next line of 'doclist' would perfomed. The final result messages warnings which call the name of function that had errors and the context of errors.

Upvotes: 0

Views: 389

Answers (1)

user1310503
user1310503

Reputation: 577

Here is some code that shows basically how you can do this. It does not use igraph objects or your functions in doclist, so you will have to adapt it to use those yourself.

First, here are two functions that raise errors:

g <- function(y) { 
    stop("g failed")
}
h <- function(y) { 
    stop("h failed")
}

And here is a cleaned up version of your function, using some different functions in doclist:

func <- function(x, remove=NULL) {
    if (!is(x, "numeric")) 
        stop("x must be a numeric")

    doclist <- list(
        sum = function(x) sum(x),
        g = function(x) g(x),
        makeMatrix = function(x) matrix(x, nrow=3, ncol=3),
        h = function(x) h(x)
    )
    doclist <- doclist[setdiff(names(doclist), remove)]

    warningsText <- ""
    result <- lapply(names(doclist), 
        function(functionName, x) {
            f <- doclist[[functionName]]
            tryCatch(f(x), 
                error = function(e) {
                    warningsText <<- paste0(warningsText, 
                        "\nError in ", functionName, ":\n", e$message)
                    return(NULL)
                }) 
        }, x)

    if (nchar(warningsText) > 0) 
        warning(warningsText)
    return(result)
}

And here is what it produces:

> func(1:2)
[[1]]
[1] 3

[[2]]
NULL

[[3]]
     [,1] [,2] [,3]
[1,]    1    2    1
[2,]    2    1    2
[3,]    1    2    1

[[4]]
NULL

Warning messages:
1: In matrix(x, nrow = 3, ncol = 3) :
  data length [2] is not a sub-multiple or multiple of the number of rows [3]
2: In func(1:2) : 
Error in g:
g failed
Error in h:
h failed

Notes:

  • For functions that raise errors, this puts NULL in the result list.
  • All the errors get put into one warning. In the example with func(1:2) this is the second warning shown.
  • A for loop would be better than lapply or sapply, but I haven't done that.
  • lapply is better than sapply, as the functions all return different kinds of objects.
  • It is best to include x in the arguments of the nameless function inside lapply and it as a third argument to lapply.
  • The first argument to lapply should be the function names, so that both the function names and the functions themselves are available to the nameless function inside lapply.

Upvotes: 1

Related Questions